不能 return 来自 Class.__new__() 的子类实例
Cannot return Subclass instance from Class.__new__()
这是 Python 3 代码:
class Class:
def __new__(cls, value):
print(__class__, cls, value)
return Subclass(value+1, value+2)
class Subclass(Class):
def __new__(cls, value, value2):
print(__class__, cls, value, value2)
return object.__new__(Subclass)
def __init__(self, *args):
print(args)
self.value = args
acctual_instance = Class(1)
print('acctual_instance:', acctual_instance.value, type(acctual_instance))
输出:
<class '__main__.Class'> <class '__main__.Class'> 1
<class '__main__.Subclass'> <class '__main__.Subclass'> 2 3
(2, 3)
(1,)
acctual_instance: (1,) <class '__main__.Subclass'>
即使我们从 Class.__new__(1)
中 return 编辑了 Subclass(2,3)
实例,acctual_instance.value
是 Class
的参数 1,而不是 (2,3)。这是预期的行为吗?为什么 Subclass.__init__()
是第二次调用?我如何 return Subclass(2,3)
来自 Class.__new__(1)
的实例?
更新:
如果从 class Subclass(Class)
中删除 Class
那么输出是:
<class '__main__.Class'> <class '__main__.Class'> 1
<class '__main__.Subclass'> <class '__main__.Subclass'> 2 3
(2, 3)
acctual_instance: (2, 3) <class '__main__.Subclass'>
关于 __new__()
的文档是 quite explicit 的:
Typical implementations create a new instance of the class by invoking the superclass's __new__()
method using super(currentclass, cls).__new__(cls[, ...])
with appropriate arguments and then modifying the newly-created instance as necessary before returning it.
这是因为 class 初始化 Class(1)
或多或少等于
obj = Class.__new__(Class, 1)
obj.__init__(1)
在您的代码中,您在 __new__()
中创建了一个完全初始化的实例
return Subclass(value+1, value+2)
这将调用 obj2 = Subclass.__new__(cls, value + 1, value + 2)
,然后是 obj2.__init__(value + 1, value + 2)
,然后是 return obj2
。
这之后是对 obj.__init__(1)
的调用,在从 __new__()
调用 return 之后,如上文所述:第二个 __init__()
使用原始参数调用(1
).因此 value == 1
。第一次构造函数调用设置的初始值被第二次构造函数调用覆盖。
您的代码的改进版本可能是
class Class:
def __new__(cls, value):
return Subclass.__new__(cls, value + 1, value + 2)
class SubClass(Class):
def __new__(cls, value1, value2):
return object.__new__(Subclass)
def __init__(self, *args):
print(args)
instance = Base(1)
print(type(instance))
但是请注意,该版本对传递给 Subclass.__new__()
的 value1
和 value2
没有任何作用。
另请注意,在 Subclass.__init__()
中,您还应该调用 super().__init__()
这是 Python 3 代码:
class Class:
def __new__(cls, value):
print(__class__, cls, value)
return Subclass(value+1, value+2)
class Subclass(Class):
def __new__(cls, value, value2):
print(__class__, cls, value, value2)
return object.__new__(Subclass)
def __init__(self, *args):
print(args)
self.value = args
acctual_instance = Class(1)
print('acctual_instance:', acctual_instance.value, type(acctual_instance))
输出:
<class '__main__.Class'> <class '__main__.Class'> 1
<class '__main__.Subclass'> <class '__main__.Subclass'> 2 3
(2, 3)
(1,)
acctual_instance: (1,) <class '__main__.Subclass'>
即使我们从 Class.__new__(1)
中 return 编辑了 Subclass(2,3)
实例,acctual_instance.value
是 Class
的参数 1,而不是 (2,3)。这是预期的行为吗?为什么 Subclass.__init__()
是第二次调用?我如何 return Subclass(2,3)
来自 Class.__new__(1)
的实例?
更新:
如果从 class Subclass(Class)
中删除 Class
那么输出是:
<class '__main__.Class'> <class '__main__.Class'> 1
<class '__main__.Subclass'> <class '__main__.Subclass'> 2 3
(2, 3)
acctual_instance: (2, 3) <class '__main__.Subclass'>
关于 __new__()
的文档是 quite explicit 的:
Typical implementations create a new instance of the class by invoking the superclass's
__new__()
method usingsuper(currentclass, cls).__new__(cls[, ...])
with appropriate arguments and then modifying the newly-created instance as necessary before returning it.
这是因为 class 初始化 Class(1)
或多或少等于
obj = Class.__new__(Class, 1)
obj.__init__(1)
在您的代码中,您在 __new__()
return Subclass(value+1, value+2)
这将调用 obj2 = Subclass.__new__(cls, value + 1, value + 2)
,然后是 obj2.__init__(value + 1, value + 2)
,然后是 return obj2
。
这之后是对 obj.__init__(1)
的调用,在从 __new__()
调用 return 之后,如上文所述:第二个 __init__()
使用原始参数调用(1
).因此 value == 1
。第一次构造函数调用设置的初始值被第二次构造函数调用覆盖。
您的代码的改进版本可能是
class Class:
def __new__(cls, value):
return Subclass.__new__(cls, value + 1, value + 2)
class SubClass(Class):
def __new__(cls, value1, value2):
return object.__new__(Subclass)
def __init__(self, *args):
print(args)
instance = Base(1)
print(type(instance))
但是请注意,该版本对传递给 Subclass.__new__()
的 value1
和 value2
没有任何作用。
另请注意,在 Subclass.__init__()
中,您还应该调用 super().__init__()