这可能已经被问到死了,但我真的认为这个问题会对某人有帮助,因为我真的找不到这个问题的答案。
我已经努力将代码简化为最小的结构(忽略了不可靠的命名)。
首先,这里是问题的堆栈跟踪:
Traceback (most recent call last):
File "C:\xx\xx\xx\main.py", line 30, in <module>
DoSomething().method()
File "C:\xx\xx\xx\main.py", line 27, in method
self.some_class_method()
File "C:\xx\xx\xx\main.py", line 12, in some_class_method
print(self.variable)
AttributeError: 'DoSomething' object has no attribute 'variable'
Process finished with exit code 1
这是失败的代码(从上到下:最低级别到最高级别,最后调用最高级别类(最高级别是最子级别)):
class ParentConfig:
def __init__(self):
pass
class SomeClass:
def __init__(self):
super().__init__()
self.variable = 'value'
def some_class_method(self):
print(self.variable)
class Config(ParentConfig, SomeClass):
def __init__(self):
super().__init__()
pass
class DoSomething(Config):
def __init__(self):
super().__init__()
pass
def method(self):
self.some_class_method()
DoSomething().method()
我可以让代码以两种方式工作:
第一,删除“ParentConfig”父类
class Config(<removed>, SomeClass):
def __init__(self):
super().__init__()
pass
第二,分别调用两个__init__s
class Config(ParentConfig, SomeClass):
def __init__(self):
ParentConfig().__init__()
SomeClass().__init__()
pass
现在,为了明确第二个“解决方案”在本例中不起作用,但它确实修复了我的程序中的问题,很抱歉没有一个完美的示例。
主要的一点是,类'DoSomething‘在调用方法时不能使用self.variable。
如果有人可以在单独调用ParentConfig().__init__()
和SomeClass().__init__()
时修复我的示例,而不是只使用super().__init__
,则可以获得额外的积分
我希望这是足够的信息。同时,我将编写一个更好的示例并编辑此示例。
编辑:
卡尔·克奈特尔斯的TLDR为新手解答:
要么从def __init__(self)
中删除ParentClass
或
将super().__init__()
添加到ParentClass中的def __init__(self)
中
发布于 2022-01-28 03:55:35
class ParentConfig:
def __init__(self):
pass
问题已经出现了。任何以ParentConfig
为基础的东西,无论是直接还是间接的,在遵循super()
链时都会停止。
class Config(ParentConfig, SomeClass):
当在Config
中调用super()
时,ParentConfig
(以及任何直接或间接将其作为基础的东西)将在SomeClass
之前考虑super()
。因此,SomeClass.__init__
不会被调用,.variable
也不会被设置。
Python处理“钻石继承”问题的方法是super()
是协作的。它不会路由到当前类的直接基类。它按照实际self
对象的方法解析顺序路由到下一个类。
在这里,它应该在ParentConfig
中使用
class ParentConfig:
def __init__(self):
super().__init__()
(或者省略__init__
,因为这是默认行为。)
初始化Config
(或DoSomething
)时,此super()
调用将按需要路由到SomeClass
,而不是object
。为什么?由于MRO,您可以在运行时检查它:
>>> Config.__mro__
(<class '__main__.Config'>, <class '__main__.ParentConfig'>, <class '__main__.SomeClass'>, <class 'object'>)
>>> DoSomething.__mro__
(<class '__main__.DoSomething'>, <class '__main__.Config'>, <class '__main__.ParentConfig'>, <class '__main__.SomeClass'>, <class 'object'>)
有关更多细节,请参见Python的超级()被认为是超级的!,这是由Python团队的一名成员(同时也是一位非常好的教师)撰写的关于这个主题的权威文章。
https://stackoverflow.com/questions/70893129
复制相似问题