.__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__()
我在理解 .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__()