2

我正在使用现有的 Django 库,并且正在创建一个我想要抽象的类。

假设有问题的班级是BaseFoo.

目前,实现有一个基类BaseFoo

每次BaseFoo创建扩展类时,元类都会将其添加到类列表中。它明确不BaseFoo通过对类名进行硬编码测试来添加:

    if name not in ('BaseFoo',):
        class_list.append(new_cls)

我希望能够写出类似的东西:

class MyBaseFoo(BaseFoo):
    class Meta:
        abstract = True

并让元类跳过所有BaseFoo抽象对象。所以我想我想知道 Django 是如何对模型做同样的事情的,以及是否有一种简单、优雅的方式来自己做这件事。

我查看了 Django 用于定义模型的一些代码,但我可以使用一些指针。此外,如果有一种更简单的方法可以做到这一点,而不必使用class Meta我也愿意。

请注意,我对这个解决方案并不特别兴奋:

class MyBaseFoo(BaseFoo):
    abstract = True

class ActualFoo1(MyBaseFoo):
    abstract = False

class ActualFoo2(MyBaseFoo):
    abstract = False
4

1 回答 1

3

无需在具体类中将 abstract 设置为 False - 仅在抽象类中具有此设置就足够了:

class_list = []
class CollectSubclasses(type):
    def __new__(cls, name, bases, attrs):
        abstract = False
        if attrs.get('abstract', False):
            abstract = True
            del attrs['abstract']
        res = super(CollectSubclasses, cls).__new__(cls, name, bases, attrs)
        if not abstract:
            class_list.append(res)
        return res

class BaseFoo(object):
    __metaclass__ = CollectSubclasses
    abstract = True

class Concrete1(BaseFoo):
    pass

class Abstract(BaseFoo):
    abstract = True

class Concrete2(Abstract):
    pass

print class_list

替代方法可能是 Python 2.6 中的类装饰器,但是,您需要从 @abstract 装饰器的 class_list 中删除该类,因为在调用装饰器时已经创建了该类(因此已经调用了元类)。

于 2010-12-27T20:30:01.950 回答