__repr__方法似乎无法自动为Exception类调用

5
我被告知,如果一个对象的__str__方法没有被创建,但是__repr__已经被创建,那么打印该对象将调用__repr__。这似乎对于普通类来说是正确的,但是当我在Exception的子类上尝试时,奇怪的是__repr__不会被调用,有人能解释一下为什么吗?
以下是示例:
class BoringError(Exception):
  def __init__(self):
    self.purpose = "Demonstration"
    self.boringLevel = 10
  def __repr__(self):
    return "I'm a message for developer"

 try: 
   if 1 != 2:
    raise BoringError 
 except BoringError as e:
   print(e.boringLevel)
   print(e)

class Tree:
  def __repr__(self):
    return "I love water"

AVL = Tree()
print(AVL)

这个程序会产生以下结果。
10

I love water

不要使用

10
I'm a message for developer
I love water

4
e.__str__ 虽然被定义了,但它只是指向了 Exception.__str__,而不是指向 BoringError.__str__ - chepner
我明白了,所以是因为调用了父类的方法。 - Stephen Fong
2
print(e) calls print(e.__str__()) not print(e.__repr__()) - Holloway
2个回答

4

__repr__仅在e.__str__解析为object.__str__时调用,这基本上像是定义了一个函数。

def __str__(self):
    return self.__repr__()

在您的情况下,object.__str__从未被调用,因为e.__str__解析为Exception.__str__,它不会调用__repr__的任何定义。比较一下:
>>> e = Exception("hi")
>>> print(e)
hi
>>> str(e)
'hi'
>>> repr(e)
"Exception('hi')"

Tree.__str__ 未定义,因此AVL.__str__确实解析为object.__str__,因此调用Tree.__repr__


3
当打印异常时,会调用__str__而不是__repr__。请参见处理异常文档

except子句可以在异常名称后指定变量。该变量绑定到一个带有存储在instance.args中的参数的异常实例。 为方便起见,异常实例定义了__str__(),因此可以直接打印参数,而无需引用.args。还可以先实例化异常,然后在需要时添加任何属性。

考虑以下内容:
try:
    raise NameError('HiThere')
except NameError as e:
    print(e)

当调用print(e)时,实例e具有一个__str__方法,该方法返回它创建时使用的参数,此处为字符串'HiThere'
这就是您可以使用print(e)而不是明确使用print(e.args)的方法。
在您的情况下,没有传递参数给BoringError,因此print(e)打印一个空字符串。
通过以下方式重写__str__方法:
 def __str__(self):
     return "I'm a message for developer"

提供预期结果。


能否以更简单的语言解释文档?它的解释有点太技术化了。 - Stephen Fong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接