Python 为什么在实例化一个类时要调用两次uuu init_uuuu方法? class颜色: 定义(cls,obj=None,*args,**kwds): 如果cls不是彩色的: 返回对象。\uuuu新建\uuuu(cls) elif类型(obj)为str: s=对象较低() 如果s在['r','red']中: 返回红色(*args,**kwds) 其他: 升值误差 其他: 提高打字错误 定义初始化(self,r,g,b): self.r=r self.g=g self.b=b def对方(自我): 未实施 def亮度(自身): 未实施 类红色(颜色): 定义初始化(self,x=1): super().\uuuu init\uuuu(x,0,0)

Python 为什么在实例化一个类时要调用两次uuu init_uuuu方法? class颜色: 定义(cls,obj=None,*args,**kwds): 如果cls不是彩色的: 返回对象。\uuuu新建\uuuu(cls) elif类型(obj)为str: s=对象较低() 如果s在['r','red']中: 返回红色(*args,**kwds) 其他: 升值误差 其他: 提高打字错误 定义初始化(self,r,g,b): self.r=r self.g=g self.b=b def对方(自我): 未实施 def亮度(自身): 未实施 类红色(颜色): 定义初始化(self,x=1): super().\uuuu init\uuuu(x,0,0),python,Python,在上面的代码中,我希望可以调用基类Color来实例化其子类对象。例如,我希望Color('r')返回一个Red且r=1的对象,Color('r',0.5)返回一个r=0.5的红色对象。然而,当我用这个做实验时,结果是 red=颜色('r') 印刷品(红色r) 打印一个字符串'r'!当我检查调用堆栈时,我发现Red对象的\uuuuu init\uuuu方法已经被调用了两次:第一次是\uuu init\uuu(),第二次是\uu init\uuu(,'r')。为什么会发生第二次呼叫 调用堆栈是 _

在上面的代码中,我希望可以调用基类
Color
来实例化其子类对象。例如,我希望
Color('r')
返回一个
Red
r=1
的对象,
Color('r',0.5)
返回一个
r=0.5
的红色对象。然而,当我用这个做实验时,结果是

red=颜色('r')
印刷品(红色r)
打印一个字符串
'r'
!当我检查调用堆栈时,我发现
Red
对象的
\uuuuu init\uuuu
方法已经被调用了两次:第一次是
\uuu init\uuu()
,第二次是
\uu init\uuu(,'r')
。为什么会发生第二次呼叫

调用堆栈是

__new__(<class '__main__.Color'>, 'r'):
    __new__(<class '__main__.Red'>):
    __new__(<class '__main__.Red'>) -> <__main__.Red object at 0x0000020AE612CF40>
    __init__(<__main__.Red object at 0x0000020AE612CF40>):
        __init__(<__main__.Red object at 0x0000020AE612CF40>, 1, 0, 0):
        __init__(<__main__.Red object at 0x0000020AE612CF40>, 1, 0, 0) -> None
    __init__(<__main__.Red object at 0x0000020AE612CF40>) -> None
__new__(<class '__main__.Color'>, 'r') -> <__main__.Red object at 0x0000020AE612CF40>
__init__(<__main__.Red object at 0x0000020AE612CF40>, 'r'):
    __init__(<__main__.Red object at 0x0000020AE612CF40>, 'r', 0, 0):
    __init__(<__main__.Red object at 0x0000020AE612CF40>, 'r', 0, 0) -> None
__init__(<__main__.Red object at 0x0000020AE612CF40>, 'r') -> None
\uuuuuuuuuuuuuuuuuuu新的(,'r'):
__新的
__新建\uuuux0()->
__init_uuz():
__初始值(,1,0,0):
__初始化(,1,0,0)->无
__init_uuz()->无
__新的(,'r')->
__初始值(,'r'):
__初始值(,'r',0,0):
__初始化(,'r',0,0)->无
__初始化(,'r')->无

因为您隐式调用了它两次

当您执行
类名(…)
时,
\uuuuuu new\uuuuuu
的结果已在其上调用了
\uuuuuuuu init\uuuuuuuuuuuu
。在
\uuuuuuuuuuuuuuuuuu
中,使用
红色(…)
调用普通对象构造,红色(…)依次调用
\uuuuuuuuuuuuuuuuuu
,然后对结果调用
\uuuuuuuuuuu init\uuuuuuuuu
,并返回新对象。然后从原始的
\uuuuu new\uuuu
调用返回该对象,它将再次被
\uuuuuu init\uuuu
-ed


为了避免双重的
\uuuuu init\uuuuuuuuuuuu
,请在
\uuuuuu new\uuuuuuuuu
中显式使用
\uuuuuuu new\uuuuuuuuuuuuuuuuuuuuuuuuuuuu
,而不是
红色()。我们应该能够复制和粘贴一个连续的代码块,执行该文件,并再现您的问题以及跟踪问题点的输出。这让我们可以根据您的测试数据和期望的输出来测试我们的建议。不接受场外链接和文本图像;我们需要您的问题是独立的,以符合本网站的目的。因为您在
\uuuuu new\uuuu
中初始化了一个完整的对象。谢谢您的回答!然而,我发现我的方法仍然无法工作,因为在
Color
\uuuuuuuuuuuuuuuu
方法返回一个
Red
对象之后,调用
Red
\uuuuuuuuuuuuu
方法并将str'r'作为参数传递。因此,
red.r
仍然是“r”而不是数字。我尝试使用
Color
元类来修改
Color('r')
的行为,结果是:)@JamesTZ:True,
'r'
仍将被传递到
\uu init\uuuu
。通常,最好只使用
\uuuuu new\uuuu
\uuuu init\uuuu
,而不是两者都使用。如果你两者都使用,你就不会为每一个使用不同的原型,这正是你看到的原因。