Python:打印自定义异常时超出了最大递归深度 [英] Python: Maximum recursion depth exceeded when printing custom exception
问题描述
以下代码引发 RuntimeError:获取对象的str时超出了最大递归深度
。我可以用两种不同的方法来解决无限递归问题,但是我不明白为什么每个修复程序都能正常工作,因此不知道使用哪个修复程序,或者两者是否正确。
The following code throws RuntimeError: maximum recursion depth exceeded while getting the str of an object
. I can resolve the infinite recursion in two different ways, but I don't understand why each fix works and thus don't know which to use, or if either are correct.
class FileError( Exception ):
def __init__( self, filename=None, *a, **k ):
#Fix 1: remove super
super( FileError, self ).__init__( self, *a, **k )
self.filename = filename
def __repr__( self ):
return "<{0} ({1})>".format( self.__class__.__name__, self.filename )
#Fix 2: explicitly define __str__
#__str__ = __repr__
print( FileError( "abc" ) )
如果我删除 super
,代码将运行,但不输出任何内容。这是没有道理的,因为根据这篇文章 __str__和__repr__之间的区别Python ,省略 __ str __
会调用 __ repr __
,但这似乎没有发生。
If I remove super
, the code runs but doesn't print anything. This doesn't make sense since according to this post, Difference between __str__ and __repr__ in Python, omitting __str__
will call __repr__
but that doesn't seem to be happening here.
如果是的话,将呼叫保留为 super
并添加 __ str__ = __repr __
,那么我得到了预期的输出,并且没有递归。
If I, instead, keep the call to super
and add __str__ = __repr__
, then I get the expected output and there is no recursion.
有人可以解释为什么存在无限递归,为什么每个更改都可以解析无限递归,以及为什么一个修复方法可能比其他修复方法更受欢迎?
Can someone explain why the infinite recursion is present, why each change resolves the inifinte recursion, and why one fix might be preferred over the other?
推荐答案
您的 super
调用是错误的: self
不应再次提供,它已经由 super
注入。这样, file_error.args [0]就是file_error
,因为您将 self
作为异常构造函数的附加参数传递了。这应该很清楚为什么解决方法1(完全删除超级调用)会有所帮助,但当然最好的解决方法是传递正确的参数:
Your super
invocation is wrong: self
should not be supplied again, it's already injected by super
. This way, file_error.args[0] is file_error
because you pass self
as an extra argument to the exception constructor. This should make it obvious why fix #1 (removing the super call altogether) helps, but of course the best fix is to pass the right arguments:
super(FileError, self).__init__(filename, *a, **k)
无限递归的原因:首先,只有 object .__ str __
代表 __ repr __
; BaseException
分别定义了 __ str __
和 __ repr __
,因此 str()
的异常会调用该重载,而不是您的 __ repr __
。 BaseException .__ str __
通常打印args元组(将使用 repr
),尽管当它包含单个参数时,它会打印 str()
The reason for the infinite recursion: First off, only object.__str__
delegates to __repr__
; BaseException
defines both __str__
and __repr__
separately, so str()
of an exception calls that overload, not your __repr__
. BaseException.__str__
usually prints the args tuple (which would use repr
), though when it contains a single argument, it prints the str()
of that single argument.
这将再次调用 BaseException .__ str __
,依此类推。修补程序2通过不首先输入 BaseException .__ str __
来代替您使用 __ repr __
来防止此循环完全触摸args元组。
This invokes BaseException.__str__
again, and so on. Fix #2 prevents this cycle by not entering BaseException.__str__
in the first place, instead using your __repr__
which does not touch the args tuple at all.
这篇关于Python:打印自定义异常时超出了最大递归深度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!