为什么不为子类调用我的元类函数?

sam*_*yse 6 python metaclass python-2.7

Python文档说类的元类可以是任何可调用的.我看到的所有例子都使用了一个类.为什么不使用功能?它是可调用的,定义相当简单.但它不起作用,我不明白为什么.

这是我的代码:

class Foo(object):
    def __metaclass__(name, base, dict):
        print('inside __metaclass__(%r, ...)' % name)
        return type(name, base, dict)
print(Foo.__metaclass__)
class Bar(Foo):
    pass
print(Bar.__metaclass__)
Run Code Online (Sandbox Code Playgroud)

这是输出:

inside __metaclass__('Foo', ...)
<unbound method Foo.__metaclass__>
<unbound method Bar.__metaclass__>
Run Code Online (Sandbox Code Playgroud)

为父类和子类定义了元类方法.为什么只为父母打电话?(是的,我尝试使用类方法和静态方法装饰我的元类,既没有工作的.是的,这似乎是一个DUP 元类不会被调用子类中的,但他们是一类,而不是功能,作为元类).

eca*_*mur 5

答案在于查找优先规则__metaclass__

适当的元类由以下优先级规则确定:

  • 如果dict['__metaclass__']存在,则使用它。
  • 否则,如果至少有一个基类,则使用其元类(此方法首先查找__class__属性,如果找不到,则使用其类型)。
  • 否则,如果__metaclass__存在名为的全局变量,则将使用它。
  • 否则,将使用旧式的经典元类(types.ClassType)。

如果我们检查Foo.__class__一下,发现它是<type 'type'>预期的,这是您调用type构造函数的元类函数所期望的Foo

__class__type的第一个参数设置type.__new__,这就是为什么在类元类中我们称为type.__new__(cls, name, bases, dict)(或super(Metaclass, cls).__new__(cls, ...))的原因。但是,如果元类是一个函数,我们就不能这样做:

>>> def __metaclass__(name, base, dict):
>>>     print('inside __metaclass__(%r, %r, %r)' % (name, base, dict))
>>>     return type.__new__(__metaclass__, name, base, dict)
>>> class Foo(object):
>>>     __metaclass__ = __metaclass__
TypeError: Error when calling the metaclass bases
    type.__new__(X): X is not a type object (function)
Run Code Online (Sandbox Code Playgroud)

同样,如果我们尝试将其设置Foo.__class__为您__metaclass__失败,则因为该__class__属性必须是一个类:

>>> Foo.__class__ = Foo.__metaclass__.__func__
TypeError: __class__ must be set to new-style class, not 'function' object
Run Code Online (Sandbox Code Playgroud)

因此,使元类类继承type而不是可调用的原因是使它们可继承。