Class 没有使用多重继承的 parent class 变量的属性
Class has no attribute of a variable from a parent class using multiple inheretance
这可能已经被问死了,但我真的认为这个问题会对某人有所帮助,因为我真的找不到问题或答案。
我努力将代码简化为最小的结构(忽略狡猾的命名)
首先是问题的堆栈跟踪:
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(最高就是最多child)):
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'parentclass
class Config(<removed>, SomeClass):
def __init__(self):
super().__init__()
pass
两个,分别调用__init__s
class Config(ParentConfig, SomeClass):
def __init__(self):
ParentConfig().__init__()
SomeClass().__init__()
pass
现在,需要明确的是,第二个 'solution' 在此示例中不起作用,但它确实解决了我程序中的问题,很抱歉没有完美的示例。
重点是class'DoSomething'调用方法时不能用self.variable
如果有人可以修复我的示例,使其在单独调用 ParentConfig().__init__()
和 SomeClass().__init__()
时起作用,但在仅使用 super().__init__
时不起作用,则加分
我希望这些信息足够了。与此同时,我将研究一个更好的示例并对其进行编辑。
编辑:
关于 Karl Knechtel 新手回答的 TLDR:
从 ParentClass
中删除 def __init__(self)
或者
在ParentClass
的def __init__(self)
中添加一个super().__init__()
class ParentConfig:
def __init__(self):
pass
问题已经出现了。任何以 ParentConfig
为基础的东西,直接或间接,在遵循 super()
链时都会在这一点停止。
class Config(ParentConfig, SomeClass):
Config
(以及直接或间接以它为基础的任何事物)将考虑 ParentConfig
before SomeClass
when super()
在 Config.__init__
中调用。 SomeClass.__init__
因此 不会 被调用,并且 .variable
未设置。
Python处理“钻石继承”问题的方法是super()
合作。它不会路由到当前class的直接基地class。它按照实际 self
对象 .
的方法解析顺序路由到 下一个 class
这里应该用在ParentConfig
:
class ParentConfig:
def __init__(self):
super().__init__()
(或者省略 __init__
,因为这是默认行为。)
初始化 Config
(或 DoSomething
)时,此 super()
调用将路由到 object
,而不是 SomeClass
,因为想要的。为什么?由于 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's super() considered super!,由 Python 开发团队成员(通常也是一位非常好的老师)撰写的关于该主题的权威文章。
这可能已经被问死了,但我真的认为这个问题会对某人有所帮助,因为我真的找不到问题或答案。
我努力将代码简化为最小的结构(忽略狡猾的命名)
首先是问题的堆栈跟踪:
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(最高就是最多child)):
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'parentclass
class Config(<removed>, SomeClass):
def __init__(self):
super().__init__()
pass
两个,分别调用__init__s
class Config(ParentConfig, SomeClass):
def __init__(self):
ParentConfig().__init__()
SomeClass().__init__()
pass
现在,需要明确的是,第二个 'solution' 在此示例中不起作用,但它确实解决了我程序中的问题,很抱歉没有完美的示例。
重点是class'DoSomething'调用方法时不能用self.variable
如果有人可以修复我的示例,使其在单独调用 ParentConfig().__init__()
和 SomeClass().__init__()
时起作用,但在仅使用 super().__init__
我希望这些信息足够了。与此同时,我将研究一个更好的示例并对其进行编辑。
编辑:
关于 Karl Knechtel 新手回答的 TLDR:
从 ParentClass
中删除def __init__(self)
或者
在ParentClass
的def __init__(self)
中添加一个super().__init__()
class ParentConfig:
def __init__(self):
pass
问题已经出现了。任何以 ParentConfig
为基础的东西,直接或间接,在遵循 super()
链时都会在这一点停止。
class Config(ParentConfig, SomeClass):
Config
(以及直接或间接以它为基础的任何事物)将考虑 ParentConfig
before SomeClass
when super()
在 Config.__init__
中调用。 SomeClass.__init__
因此 不会 被调用,并且 .variable
未设置。
Python处理“钻石继承”问题的方法是super()
合作。它不会路由到当前class的直接基地class。它按照实际 self
对象 .
这里应该用在ParentConfig
:
class ParentConfig:
def __init__(self):
super().__init__()
(或者省略 __init__
,因为这是默认行为。)
初始化 Config
(或 DoSomething
)时,此 super()
调用将路由到 object
,而不是 SomeClass
,因为想要的。为什么?由于 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's super() considered super!,由 Python 开发团队成员(通常也是一位非常好的老师)撰写的关于该主题的权威文章。