1. 没有指定 metaclass 参数

  • 执行顺序: 先执行 __new__ 方法,然后再执行 __init__ 方法

class Foo(object):
    def __new__(cls, *args, **kwargs):
        print(1)
        return object.__new__(cls)

    def __init__(self):
        print(2)
        self.name = 'Kevin'


obj = Foo()

2. 类指定了 metaclass 参数

  • metaclass 参数的作用: 指定当前类是由谁创建

  • 执行顺序:

    • 创建类时: 先执行type下的__init__方法

    • 实例化对象时: 当一个类实例化时会执行type下的__call__方法,而__call__方法的返回值就是实例化的对象

      • __call__方法内部调用:
        • 类.__new__ -> 创建对象
        • 类.__init__ -> 对象属性的初始化

  • 以下面的例子为前提的辅助说明:

    • Foo是一个类
    • Foo类是MyType的一个“对象”,因为Foo是由MyType所创建的,所以Foo()在实例化的时候会执行MyType下的__call__方法

class MyType(type):  # 必须继承type方法,由type方法创建类
    def __init__(self, *args, **kwargs):
"""
        当创建 Foo 类的时候就会执行当前类的 __init__ 方法(即:type下的__init__方法)
        """
        super(MyType, self).__init__(*args, **kwargs)  # 调用type类下的__init__方法

    def __call__(cls, *args, **kwargs):
"""
        当实例化 Foo 类的时候就会执行当前类的 __call__ 方法(即:type下的__call__方法),然后通过 __call__ 方法调用 Foo 类的 __new__ 和 __init__ 方法
        :param cls: cls 就是 Foo 类
        :return: __call__ 的返回值就是Foo所实例化出来的对象(即:f_obj = 当前类的__call__方法的返回值)
        """
        obj = cls.__new__(cls)  # 调用 Foo 类下的__new__方法创建对象
        cls.__init__(obj, *args, **kwargs)  # 调用 Foo 类下的__init__方法初始化对象的属性
        return obj  # __call__ 的返回值就是Foo所实例化出来的对象(即:f_obj = 当前类的__call__方法的返回值)


class Foo(object, metaclass=MyType):
    def __new__(cls, *args, **kwargs):
        return object.__new__(cls)

    def __init__(self):
        self.name = 'Kevin'


f_obj = Foo()

print(f_obj.name)  # Kevin