我在这里再修改仔细说明下吧
元类是定义类结构属性的, 而类里的 "__new__", "__init__" 方法, 是处理类实例用的
我们所定义的每一个类, 都可以理解为是 type 的一个实例
class Foo(object):
version = "1.0.1"
pass
print(Foo.version) # 1.0.1
print(Foo.__name__) # Foo
# ------------
# 使用type创建类是一样的
Foo = type("Foo", (object,), dict(version="1.0.1"))
print(Foo.version) # 1.0.1
print(Foo.__name__) # Foo
好, 说回到 "__new__" 和 "__call__"
元类中, "__new__" 会在你定义类的时候执行, 只执行一次, 如果有两个类使用了这个元类, OK, 会执行两次
class FooMeta(type):
def __new__(meta, name, bases, dct):
print("metaclass __new__")
return type(name, bases, dct)
class Foo():
__metaclass__ = FooMeta
# 没有任何代码了, 你会看到 print了metaclass __new__
# 如果你细心, 并联系上面说的, 理解为
# Foo = type("Foo", tuple(), dict())
# 就明白 FooMeta.__new__原来就是 type.__new__
# Foo 是type的一个实例
# 这是为什么定义元类都要base type的原因: class FooMeta(type)
# 如果你定义 __metaclass__ = type 并没什么错, 因为本来默认就是这样
而__call__会在你每次实例化的时候调用, 其实和Foo.__new__是一样的, 意思是, 如果你的Foo定义了__new__, 元类中的__call__便不会执行
class FooMeta(type):
def __new__(meta, name, bases, dct):
print("metaclass __new__")
return type(name, bases, dct)
def __call__(self, *args, **kwargs):
print("meta __call__")
return "hello"
class Foo():
__metaclass__ = FooMeta
def __new__(cls, *args, **kwargs):
print("Foo __new__")
return "hello"
f = Foo()
print(f)
# 输出结果
# metaclass __new__
# Foo __new__
# hello
元类的 "__new__" 可以变更你所定义的类型, 我在这里定义Foo成了一个list
# -*- coding: utf-8 -*-
class FooMeta(type):
def __new__(cls, name, bases, dct):
return [1, 2, 3, 4]
# 这里相当于执行 Foo = [1, 2, 3, 4]
class Foo():
__metaclass__ = FooMeta
print(Foo) # [1, 2, 3, 4]
print(Foo[0:2]) # [1, 2]
print(Foo.pop()) # 4
写这么多很辛苦的, 能正解理解metaclass的人非常的少, 不知题主要怎么感谢我