在阅读部分Django源代码后,我想在下面做一些测试和编写代码,看看元类是如何工作的:
class MyMeta(type):
def __new__(cls, name, bases, attrs):
print cls, name, bases, attrs
return super(MyMeta, cls).__new__(cls, name, bases, attrs)
class AttrFiled(object): pass
class Test(MyMeta):
name = AttrField()
总是抱怨:
TypeError: __new__() takes at least 2 arguments (1 given)
我添加修改如下:
def with_metaclass(meta, *bases): # copied from Django code.
return meta("NewBase", bases, {})
class Test(with_metaclass(MyMeta)):
name = CharField()
它有效。
我也读过这个What is a metaclass in Python?。 但仍感到困惑。
提前致谢!
答案 0 :(得分:4)
with_metaclass
最初是在six
库中引入的(如果我没记错的话),这简化了从Python 2到Python 3的过渡。这是一个聪明的技巧,使代码与它们兼容。 / p>
Python 2具有以下语法来声明使用元类:
class Foo(object):
__metaclass__ = FooMeta
Python 3,有一个不同的:
class Foo(metaclass=FooMeta):
pass
with_metaclass(meta)
做了什么:它直接使用meta
元类'构造函数创建一个中间临时类,并从中派生出类。所以Pythons - 2和3都很高兴。
您还应该阅读有关此主题的Python文档:http://docs.python.org/3/reference/datamodel.html#metaclasses
在您的具体情况下,当您撰写class Test(MyMeta):
时,您只是声明一个源自Test
的元类 MyMeta
。要制作类,您需要编写
class Test:
__metaclass__ = MyMeta
或
class Test(metaclass=MyMeta):
...
取决于你拥有的python版本。或者,如果您不确定是否需要支持Python 2,则只需使用with_metaclass
,它也可以。