Python文档说metaclass of a class can be any callable。我看到的所有例子都使用了一个类。为什么不使用功能?它是可调用的,定义相当简单。但它不起作用,我不明白为什么。
这是我的代码:
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__)
这是输出:
inside __metaclass__('Foo', ...)
<unbound method Foo.__metaclass__>
<unbound method Bar.__metaclass__>
为父类和子类定义了元类方法。为什么只为父母打电话? (是的,我尝试为我的元类使用classmethod和staticmethod装饰器,但都不起作用。是的,这似乎是Metaclass not being called in subclasses的重复,但它们是一个类,而不是一个函数,作为一个元类。)
答案 0 :(得分:5)
答案在precedence rules for __metaclass__
lookup:
适当的元类由以下优先规则决定:
- 如果
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)
同样,如果我们尝试将Foo.__class__
设置为您的__metaclass__
,则会失败,因为__class__
属性必须是一个类:
>>> Foo.__class__ = Foo.__metaclass__.__func__
TypeError: __class__ must be set to new-style class, not 'function' object
因此,使元类类继承type
而不仅仅是callables的原因是使它们可以继承。