and*_*cal 9 python recursion repr custom-exceptions
以下代码抛出RuntimeError: maximum recursion depth exceeded while getting the str of an object.我可以用两种不同的方式解决无限递归,但我不明白为什么每种修复都有效,因此不知道使用哪种,或者两种方法是否正确.
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" ) )
Run Code Online (Sandbox Code Playgroud)
如果我删除super,代码运行但不打印任何东西.这没有意义,因为根据这篇文章,Python中的__str__和__repr__之间的区别,省略__str__将调用,__repr__但这似乎不会发生在这里.
相反,如果我继续调用super并添加__str__ = __repr__,那么我得到预期的输出并且没有递归.
有人可以解释为什么无限递归存在,为什么每次更改都会解决inifinte递归,以及为什么一个修复可能比另一个更优先?
小智 4
您的super调用是错误的:self不应再次提供,它已由 注入super。这样,file_error.args[0] is file_error因为您将self作为额外参数传递给异常构造函数。这应该很明显为什么修复#1(完全删除 super 调用)有帮助,但当然最好的修复是传递正确的参数:
super(FileError, self).__init__(filename, *a, **k)
Run Code Online (Sandbox Code Playgroud)
无限递归的原因:首先,仅object.__str__委托给__repr__; BaseException分别定义__str__和__repr__,因此str()异常会调用重载,而不是您的__repr__. BaseException.__str__通常打印 args 元组(将使用repr),但当它包含单个参数时,它会打印该str()单个参数的 。
这会BaseException.__str__再次调用,依此类推。修复 #2 通过不BaseException.__str__首先输入来防止此循环,而是使用__repr__根本不触及 args 元组的 which 。