JK *_*iho 1 python recursion inheritance exception
我有一个由三个类组成的继承链:Baz继承自Bar继承自Foo.我想在Foo类中定义一个方法,当在子类中调用时,返回其父类的输出,并附加自己的东西.这是所需的输出:
>>> foo = Foo()
>>> bar = Bar()
>>> baz = Baz()
>>> print foo.get_defining_fields()
['in Foo']
>>> print bar.get_defining_fields()
['in Foo', 'in Bar']
>>> print baz.get_defining_fields()
['in Foo', 'in Bar', 'in Baz']
Run Code Online (Sandbox Code Playgroud)
问题是,我误解了super()由子类调用的超类方法或其他一些子类化细节的使用.这个位工作正常:
>>> print foo.get_defining_fields()
['in Foo']
Run Code Online (Sandbox Code Playgroud)
但bar.get_defining_fields()产生一个无限循环,运行自己直到a RuntimeError被提升而不是foo.get_defining_fields像我想要的那样召唤并停在那里.
这是代码.
class Foo(object):
def _defining_fields(self):
return ['in Foo']
def get_defining_fields(self):
if self.__class__ == Foo:
# Top of the chain, don't call super()
return self._defining_fields()
return super(self.__class__, self).get_defining_fields() + self._defining_fields()
class Bar(Foo):
def _defining_fields(self):
return ['in Bar']
class Baz(Bar):
def _defining_fields(self):
return ['in Baz']
Run Code Online (Sandbox Code Playgroud)
所以get_defining_fields在超类中定义,并且其中的super()调用self.__class__用于尝试将正确的子类名称传递给每个子类中的调用.在Bar中调用时,它会解析为super(Bar, self).get_defining_fields()返回的列表foo.get_defining_fields()将被添加到返回的列表中far.get_defining_fields().
如果你正确理解Python的继承机制和内部工作原理可能是一个简单的错误super(),但是因为我显然没有,如果有人能指出我这样做的正确方法,我会很感激.
编辑:根据丹尼尔罗斯曼的回答,我尝试用super()这种形式替换呼叫:return super(Foo, self).get_defining_fields() + self._defining_fields()
现在无限递归不再发生,但在调用时出现了不同的错误bar.get_defining_fields():
AttributeError: 'super' object has no attribute 'get_defining_fields'
Run Code Online (Sandbox Code Playgroud)
还有别的东西还不对.
编辑:是的,终于找到了我在这里失踪的东西.将丹尼尔的最新答案标记为已接受的答案.
问题出在这里:
return super(self.__class__, self)...
Run Code Online (Sandbox Code Playgroud)
self.__class__总是指当前的具体类.所以在Bar中,它指的是Bar,而在Baz中,它指的是Baz.所以,Bar调用了超类的方法,但self.__class__仍然指的是Bar,而不是Foo.所以你将获得无休止的递归.
这就是为什么你必须总是特别在super中引用这个类.像这样:
return super(Foo, self)...
Run Code Online (Sandbox Code Playgroud)
编辑权限,因为只有顶级类定义get_defining_fields.
你真是错误地对待这个问题.这根本不是一份工作super.我认为你可能会获得更好的迭代结果self.__class__.__mro__,这是访问超类的方法解析顺序的方法:
class Foo(object):
def _defining_fields(self):
return ['in Foo']
def get_defining_fields(self):
fields = []
for cls in self.__class__.__mro__:
if hasattr(cls, '_defining_fields'):
fields.append(cls._defining_fields(self))
return fields
Run Code Online (Sandbox Code Playgroud)
¬
| 归档时间: |
|
| 查看次数: |
1583 次 |
| 最近记录: |