python跳出深度循环,Python:打印自定义异常时超出了最大递归深度

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 "".format( self.__class__.__name__, self.filename )

#Fix 2: explicitly define __str__

#__str__ = __repr__

print( FileError( "abc" ) )

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.

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?

解决方案

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)

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.

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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值