.__new__function 在此示例中如何工作?

How is the .__new__function working in this example?

我在理解 .new 魔术方法如何创建 类 时遇到一些问题。下面是我正在使用的 API 的示例,它使用元 类 从数据库中的信息动态创建对象。

class Metaclass(type):
    def __new__(cls, name, bases, dict_):
        print(f' cls - {cls}')
        print(f' name - {name}')
        print(f' bases - {bases}')
        return super(Metaclass, cls).__new__(cls, name, bases, dict_)

class MyObject(object, metaclass=Metaclass):
    pass

class PrimaryObject(MyObject):
    pass

class SecondaryObject(MyObject):
    pass

test = PrimaryObject()

运行 此代码导致实例化一个 PrimaryObject,它继承自 MyObject,后者又继承自元类。然后调用元类中的新魔术方法,它遍历所有从元类继承的对象,甚至那些没有被调用的对象:

<class '__main__.Metaclass'>
MyObject
(<class 'object'>,)
<class '__main__.Metaclass'>
PrimaryObject
(<class '__main__.MyObject'>,)
<class '__main__.Metaclass'>
SecondaryObject
(<class '__main__.MyObject'>,)
<__main__.PrimaryObject object at 0x000002214A6786D0>

new 方法如何接收这些参数,因为没有向它传递任何参数?它们是从调用它的对象中解析出来的吗?如果是这样,它为什么以及如何遍历从该对象继承但未实例化的其他对象 (SecondaryObject)?

谢谢

"...这又继承自 metaclass..."

这是您假设中的错误部分。 来自 metaclass.

的那些 class 中的 None "inherit"

元class 用于构建它们 - classes 本身 - 仅一次 每个 class。那就是调用 __new__ 的时间:当 Python 执行 class 语句(连同 class 主体)。

实例化 PrimaryObject 将不再调用 metaclass __new__ - 只需在 test = ... 行之前添加另一个打印语句,您就会看到这一点。

但是,如果您希望在创建使用元class创建的 classes 的实例时调用元class 上的方法,那就是 __call__ 方法,而不是 __new__。当您在 metaclass 调用中调用 super().__call__(...) 时,它会 运行 type.__call__,这又是 运行 的 class __new____init__ 方法,创建一个新实例。

print("defining the metaclass")

class Metaclass(type):
    def __new__(cls, name, bases, dict_):
        print(f' cls - {cls}')
        print(f' name - {name}')
        print(f' bases - {bases}')
        return super(Metaclass, cls).__new__(cls, name, bases, dict_)
    def __call__(cls, *args, **kw):
        print(f"Creating a new instance of {cls.__name__}")
        return super().__call__(*args, **kw)

print("Creating the classes that use the metaclass")

class MyObject(object, metaclass=Metaclass):
    pass

class PrimaryObject(MyObject):
    pass

class SecondaryObject(MyObject):
    pass

print("Creating a class instance")

test = PrimaryObject()

metaclass 是 class 的类型。根据您的代码,比较

>>> type(MyObject)
<class '__main__.Metaclass'>
>>> type(int)
<class 'type'>

最终,所有元classes 继承自type


class 语句是一种用于对某些元class 进行隐式调用的构造。

# A = type('A', (), {})
class A:
    pass

# MyObject = Metaclass('MyObject', (), {})
class MyObject(metaclass=Metaclass):
    pass

How the metaclass is chosen 在 Python 语言参考中进行了概述。


与所有类型一样,对类型本身的调用会调用其 __new__ 方法,因此

MyObject = Metaclass('MyObject', (), {})

大致相当于

MyObject = Metaclass.__new__(Metaclass, 'MyObject', (), {})
if isinstance(MyObject, Metaclass):
    MyObject.__init__()