如何在 Python 中创建一个行为类似于 Django 抽象基类的类?

Posted

技术标签:

【中文标题】如何在 Python 中创建一个行为类似于 Django 抽象基类的类?【英文标题】:How do I create a class in Python that behaves like Django's abstract base class? 【发布时间】:2011-05-31 07:13:06 【问题描述】:

我正在使用现有的 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

【问题讨论】:

name not in ('BaseFoo') 不会像您认为的那样做 - 它会检查 name 是否是 BaseFoo 的子字符串(所以对于 name = 'Foo',这将是 False)。要创建一个单例元组,请使用('BaseFoo',)(注意尾随逗号)——但话说回来,为什么不用name != 'BaseFoo' +1(抵消)为什么要投反对票?这个问题到底有什么问题? 是的,我的代码中有错字。这是混淆代码......原来的版本实际上是name not in ('BaseFoo','OtherBaseFoo'),但我想简化......哎呀。 @bob 是的,有些人不高兴 【参考方案1】:

无需在具体类中将 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 中删除该类,因为它已经在调用装饰器时创建(因此元类已经被调用)。

【讨论】:

+1 不错的解决方案。 abstract=False 真的会导致它是抽象的吗? @kevpie:最初没有,但现在有。

以上是关于如何在 Python 中创建一个行为类似于 Django 抽象基类的类?的主要内容,如果未能解决你的问题,请参考以下文章

我想在 iPad 应用程序中创建一个行为类似于操作表的自定义视图

如何在 Python 中创建类似于以下代码示例的径向集群?

一个类似于 dict 的 python 类

如何在 SQL Server [2005] 中创建类似于 .dbo 的架构

如何在 postgresql 中创建只读视图,类似于 oracle?

如何在 Android 中创建类似于“选项卡布局”的圆形数组?