元类可以调用吗?
Can metaclass be any callable?
吸引眼球:
我认为文档可能有误!
根据 Python 2.7.12 文档,3.4.3。自定义 class 创建:
__metaclass__
This variable can be any callable accepting
arguments for name, bases, and dict. Upon class creation, the callable
is used instead of the built-in type()
.
New in version 2.2.
然而,this article 认为:
Q: Wow! Can I use any type object as the __metaclass__
?
A: No. It must be a subclass of the type of the base object. ...
所以我自己做了一个实验:
class metacls(list): # <--- subclassing list, rather than type
def __new__(mcs, name, bases, dict):
dict['foo'] = 'metacls was here'
return type.__new__(mcs, name, bases, dict)
class cls(object):
__metaclass__ = metacls
pass
这给了我:
Traceback (most recent call last):
File "test.py", line 6, in <module>
class cls(object):
File "test.py", line 4, in __new__
return type.__new__(mcs, name, bases, dict)
TypeError: Error when calling the metaclass bases
type.__new__(metacls): metacls is not a subtype of type
那么文档真的错了吗?
不,任何可调用的都可以。在您的情况下, type.__new__()
方法有一个您违反的限制;这与您分配给 __metaclass__
.
的内容无关
一个函数是可调用的:
def metaclass_function(name, bases, body):
return type(name, bases, body)
这只是 returntype()
的结果(不是 type.__new__()
),但它 只是一个可调用的 。 return 值被用作 作为 class。你真的可以 return 任何东西:
>>> class Foo(object):
... __metaclass__ = lambda *args: []
...
>>> Foo
[]
此处的可调用对象生成了一个列表实例,因此 Foo
绑定到一个列表。不是很有用,不过只是调用了__metaclass__
产生了something,那个something就直接用了
在您的示例中,type.__new__()
的第一个参数 不是类型 , 调用 失败. mcs
绑定到 list
,而不是 type
的(subclass)。 type.__new__()
可以自由设置此类限制。
现在,因为元class 仍然绑定到 class 对象(type(ClassObj)
return 它)并且在解析属性查找时使用它在 class 对象上(属性在 class MRO 中不可用),通常 honking good idea 使其成为 subclass 的 type
,因为这可以让您正确实现 __getattribute__
之类的东西。正是出于这个原因,type.__new__()
对可以作为第一个参数传入的内容进行了限制;这是 type()
附加到 class 对象的第一个参数 returned.
吸引眼球:
我认为文档可能有误!
根据 Python 2.7.12 文档,3.4.3。自定义 class 创建:
__metaclass__
This variable can be any callable accepting arguments for name, bases, and dict. Upon class creation, the callable is used instead of the built-intype()
.New in version 2.2.
然而,this article 认为:
Q: Wow! Can I use any type object as the
__metaclass__
?A: No. It must be a subclass of the type of the base object. ...
所以我自己做了一个实验:
class metacls(list): # <--- subclassing list, rather than type
def __new__(mcs, name, bases, dict):
dict['foo'] = 'metacls was here'
return type.__new__(mcs, name, bases, dict)
class cls(object):
__metaclass__ = metacls
pass
这给了我:
Traceback (most recent call last):
File "test.py", line 6, in <module>
class cls(object):
File "test.py", line 4, in __new__
return type.__new__(mcs, name, bases, dict)
TypeError: Error when calling the metaclass bases
type.__new__(metacls): metacls is not a subtype of type
那么文档真的错了吗?
不,任何可调用的都可以。在您的情况下, type.__new__()
方法有一个您违反的限制;这与您分配给 __metaclass__
.
一个函数是可调用的:
def metaclass_function(name, bases, body):
return type(name, bases, body)
这只是 returntype()
的结果(不是 type.__new__()
),但它 只是一个可调用的 。 return 值被用作 作为 class。你真的可以 return 任何东西:
>>> class Foo(object):
... __metaclass__ = lambda *args: []
...
>>> Foo
[]
此处的可调用对象生成了一个列表实例,因此 Foo
绑定到一个列表。不是很有用,不过只是调用了__metaclass__
产生了something,那个something就直接用了
在您的示例中,type.__new__()
的第一个参数 不是类型 , 调用 失败. mcs
绑定到 list
,而不是 type
的(subclass)。 type.__new__()
可以自由设置此类限制。
现在,因为元class 仍然绑定到 class 对象(type(ClassObj)
return 它)并且在解析属性查找时使用它在 class 对象上(属性在 class MRO 中不可用),通常 honking good idea 使其成为 subclass 的 type
,因为这可以让您正确实现 __getattribute__
之类的东西。正是出于这个原因,type.__new__()
对可以作为第一个参数传入的内容进行了限制;这是 type()
附加到 class 对象的第一个参数 returned.