I was told that if an obj's __str__
method isn't created but __repr__
is created then printing the obj will invoke __repr__
. That appears to be true for normal class, but when I try it on Exception's subclass, it is weird that __repr__
doesn't get invoked, could anyone explain why?
Here's an example
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)
This program produces the following result
10
I love water
Instead of
10
I'm a message for developer
I love water
__repr__
is only invoked if e.__str__
resolves to object.__str__
, which is basically defined like
def __str__(self):
return self.__repr__()
In your case, object.__str__
is never invoked, because e.__str__
resolves to Exception.__str__
, which does not invoke any definition of __repr__
. Compare:
>>> e = Exception("hi")
>>> print(e)
hi
>>> str(e)
'hi'
>>> repr(e)
"Exception('hi')"
Tree.__str__
is not defined, so AVL.__str__
does resolve to object.__str__
, hence Tree.__repr__
gets called.
When an exception is printed __str__
is called not __repr__
. See the handling exception documentation:
The except clause may specify a variable after the exception name. The variable is bound to an exception instance with the arguments stored in
instance.args
. For convenience, the exception instance defines__str__()
so the arguments can be printed directly without having to reference.args
. One may also instantiate an exception first before raising it and add any attributes to it as desired.
Consider the following:
try:
raise NameError('HiThere')
except NameError as e:
print(e)
When print(e)
is called, the instance e
has a __str__
method that returns the arguments it was created with, in this case the string 'HiThere'
.
That's how you can use print(e)
instead of explicitely using print(e.args)
.
In your case, there are no arguments passed to BoringError
, therefore print(e)
prints an empty string.
Overriding the __str__
method with:
def __str__(self):
return "I'm a message for developer"
gives the expected result.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With