python - 元类可以调用吗?

标签 python python-2.7 class types metaclass

为了吸引眼球:

我认为文档可能有误!

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

__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)

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

>>> class Foo(object):
...     __metaclass__ = lambda *args: []
...
>>> Foo
[]

这里的可调用对象产生了一个列表实例,所以 Foo 被绑定(bind)到一个列表。不是很有用,但是 __metaclass__ 只是被调用来产生 something,并且直接使用了 something。

在您的示例中,type.__new__() 的第一个参数不是类型那个调用 失败了。 mcs 绑定(bind)到 list,而不是 type 的(子类)。 type.__new__() 可以自由设置此类限制。

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

关于python - 元类可以调用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38641300/

相关文章:

python - 如何根据系列的实际值设置 x 刻度标签

python - 在django中设置一个全局变量

Python 无法将毫秒转换为日期时间并返回

java - Android 无法实例化 Activity : Didn't find class on path

python - Flask OAuth Github POST 请求

python - 在 Django 中生成带有内联摘要的列表/报告

python - 在不安装 Python 的情况下,在 Cloudera 虚拟机上安全地拥有两个版本的 Python

python - 如何返回字母子串?

javascript - 无法在自己的类中调用静态函数

class - 在哪里可以找到标准 Java 类的代码?