关于元类:Python:元数据一直向下

Python: Metaclasses all the way down

我有一个涉及Python元类的深奥问题。我正在为Web服务器端代码创建一个python包,它将使通过客户端代理访问任意python类变得容易。我的代理生成代码需要一个包含在API中的所有Python类的目录。为了创建这个目录,我使用__metaclass__特殊属性将钩子放入类创建过程中。具体来说,"已发布"API中的所有类都将子类化一个特定的基类,即PythonDirectPublic,它本身有一个__metaclass__,它被设置为记录有关类创建的信息。

到现在为止,一直都还不错。更复杂的是,我希望我的PythonDirectPublic本身从第三方类(enthought.traits.api.HasTraits)继承。这个第三方类也使用__metaclass__

那么管理两个元类的正确方法是什么呢?我的元类应该是恩萨斯元类的一个子类吗?或者我应该在我的元类的__new__方法中调用enthouse的元类来获取我将返回的类型对象吗?或者在这种特殊的情况下还有其他神秘的咒语可以使用吗?


Should my metaclass be a subclass of Enthought's metaclass?

我相信这是你唯一的选择。如果派生类的元类不是它所有基的元类的子类,那么当您试图创建派生类时,Python将抛出一个typeerror。所以你的PythonDirectPublic的元类应该看起来像

1
2
3
4
5
6
7
8
9
10
11
12
13
class DerivedMetaClass(BaseMetaClass):
    def __new__(cls, name, bases, dct):
        # Do your custom memory allocation here, if any

        # Now let base metaclass do its memory allocation stuff
        return BaseMetaClass.__new__(cls, name, bases, dct)

    def __init__(cls, name, bases, dct):
        # Do your custom initialization here, if any
        # This, I assume, is where your catalog creation stuff takes place

        # Now let base metaclass do its initialization stuff
        super(DerivedMetaClass, cls).__init__(name, bases, dct)

如果您无法访问第三方基类的元类定义,可以将BaseMetaClass替换为enthought.traits.api.HasTraits.__metaclass__。它很冗长,但会起作用的。


Specifically, all of the classes in the"published" API will subclass a particular base class, PythonDirectPublic

您可以递归地使用pythondDirectPublic.subclasss()的结果,而不是添加另一个元类。