Python:打印自定义异常时超出了最大递归深度 [英] Python: Maximum recursion depth exceeded when printing custom exception

查看:211
本文介绍了Python:打印自定义异常时超出了最大递归深度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码引发 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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆