元类可以任何可调用的吗?

nal*_*zok 6 python types metaclass class python-2.7

抓住你的眼睛:

我认为文档可能有误!

根据Python 2.7.12文档,3.4.3.自定义类创建:

__metaclass__此变量可以是name,bases和dict的任何可调用接受参数.在创建类时,使用callable而不是内置函数type().

2.2版中的新功能.

但是,本文认为:

:哇!我可以使用任何类型的对象作为__metaclass__

:不可以.它必须是基础对象类型的子类....

所以我自己做了一个实验:

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
Run Code Online (Sandbox Code Playgroud)

这给了我:

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
Run Code Online (Sandbox Code Playgroud)

那文件真的错了吗?

Mar*_*ers 5

不,任何可赎回的人都会这样做.在您的情况下,该type.__new__()方法有违反您的限制; 这与你指定的内容无关__metaclass__.

函数是可调用的:

def metaclass_function(name, bases, body):
    return type(name, bases, body)
Run Code Online (Sandbox Code Playgroud)

这个只返回type()(not type.__new__())的结果,但它只是一个可调用的.返回值用作.你真的可以归还任何东西:

>>> class Foo(object):
...     __metaclass__ = lambda *args: []
...
>>> Foo
[]
Run Code Online (Sandbox Code Playgroud)

这里callable生成了一个列表实例,因此Foo被绑定到一个列表.不是很有用,但__metaclass__只是被调用来产生一些东西,并且直接使用某些东西.

在你的榜样,第一个参数type.__new__()不是一个类型,它是该调用失败.mcs是绑定的list,而不是(子类)type.type.__new__()可以自由设置这样的限制.

现在,因为元类仍然绑定到类对象(type(ClassObj)返回它)并且在解析类对象上的属性查找时使用它(其中属性在类MRO中不可用),它通常是一个好主意使它成为一个子类type,因为它为你提供了正确的实现__getattribute__.正是出于这个原因,type.__new__()对可以作为第一个参数传递的内容进行限制; 它是type()附加到返回的类对象的第一个参数.