Python 为什么不是';我的元类函数是否为子类调用?

Python 为什么不是';我的元类函数是否为子类调用?,python,python-2.7,metaclass,Python,Python 2.7,Metaclass,Python文档说。我看到的所有示例都使用一个类。为什么不使用函数呢?它是可调用的,并且定义起来相当简单。但它不起作用,我不明白为什么 这是我的密码: class Foo(object): def __metaclass__(name, base, dict): print('inside __metaclass__(%r, ...)' % name) return type(name, base, dict) print(Foo.__metaclass_

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__)
以下是输出:

inside __metaclass__('Foo', ...)
<unbound method Foo.__metaclass__>
<unbound method Bar.__metaclass__>
内部的元类('Foo',…)
元类方法是为父类和子类定义的。为什么只有家长会打电话?(是的,我尝试在我的元类中使用classmethod和staticmethod装饰器,两者都不起作用。是的,这似乎是重复的,但它们作为元类是类,而不是函数。)

答案如下:

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

  • 如果存在
    dict[''元类]
    ,则使用它
  • 否则,如果至少有一个基类,则使用其元类(这将首先查找
    \uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
  • 否则,如果名为
    \uuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
    的全局变量存在,则使用它
  • 否则,将使用老式的经典元类(
    types.ClassType
如果我们检查
Foo.\uuuu class\uuuu
我们会发现它是
,它被期望作为名为
type
的元类函数来构造
Foo

\uuuu class\uuuuu
类型设置为
类型的第一个参数。\uuuu new\uuuuu
,这就是为什么我们在类中称为
类型的元类。\uuu new\uuuu(cls,name,base,dict)
(或
超级(元类,cls)。\uu new\uuu(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.\uuuuuu class\uuuuuu
设置为您的
\uuuuuuu元类\uuuuuuuuu
,它将失败,因为
\uuuuuuu class\uuuuuuuuuu
属性必须是一个类:

>>> Foo.__class__ = Foo.__metaclass__.__func__
TypeError: __class__ must be set to new-style class, not 'function' object

因此,使元类类继承
类型
,而不仅仅是可调用的,是为了使它们可继承。

我添加了一个指向文档相关部分的链接。请检查一下这是你的想法,我不太明白。运行时是否在某个点尝试将
Foo.\uuuuuu class\uuuuuuuuu
设置为给定的
\uuuuuuuuuuu元类\uuuuuuuuuuuuuu
?或者是“程序员的责任”@SylvainLeroux,如果你调用
type.\uuuuu new\uuuu(cls…)
(或者,相当于
super(MyMetaclass,cls)。\uuu new\uuu(cls…)
)。我会澄清的,谢谢。