__metaclass__ 不是强制使用元类吗?
我一直在尝试学习Python中的 metaclasses(元类)。我明白了大概的意思,但就是不知道怎么启动这个机制。我的理解是,当你构建一个类 K 时,可以通过在全局或类级别设置 __metaclass__
为 M 来指定 M 作为这个类的元类。为了测试这个,我写了以下程序:
p = print
class M(type):
def __init__(*args):
type.__init__(*args)
print("The rain in Spain")
p(1)
class ClassMeta:
__metaclass__ = M
p(2)
__metaclass__ = M
class GlobalMeta: pass
p(3)
M('NotMeta2', (), {})
p(4)
但是,当我运行它时,得到的输出是:
C:\Documents and Settings\Daniel Wong\Desktop>python --version Python 3.0.1 C:\Documents and Settings\Daniel Wong\Desktop>python meta.py 1 2 3 The rain in Spain 4
难道在1和2之后我不应该看到“西班牙的雨”吗?这是怎么回事呢?
3 个回答
2
在Python 3.0中,元类的语法发生了变化。以前的 __metaclass__
属性在类和模块中都很特别,但现在不再是这样了。如果你想实现你想要的功能,需要在 class
语句中把 metaclass
作为一个关键字参数来指定:
p = print
class M(type):
def __init__(*args):
type.__init__(*args)
print("The rain in Spain")
p(1)
class ClassMeta(metaclass=M): pass
这样就能得到:
1
The rain in Spain
正如你所期待的那样。
2
在Python 2.6(以及更早的版本)中,这样做是符合你预期的,但在3.0版本中,元类的指定方式有所不同:
class ArgMeta(metaclass=M): ...
14
在你使用的Python 3中,元类是通过在类定义时使用一个关键词参数来指定的:
class ClassMeta(metaclass=M):
pass
使用 __metaclass__
这个类属性或者全局变量的写法是Python 2.x时代的旧语法,现在已经不再支持了。想了解更多,可以查看“Python 3的新变化”和PEP 2115。