Why does __init__ of Exception require positional (not keyword) arguments in order to stringify exception correctly?
Question:
Can someone clarify the role of super().__init__(a, b, c)
in making the second assertion pass? It will fail without it (empty string is returned from str
).
Per my understanding Exception
is a built-in type that takes no keyword arguments.
But what exactly is happening in Exception
when the super().__init__(a, b, c)
is called?
Can calling init
like that have some unwanted side-effects?
class MyException(Exception):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
super().__init__(a, b, c)
e1 = MyException('a', 'b', 'c')
assert str(e1) == "('a', 'b', 'c')"
e2 = MyException(a='a', b='b', c='c')
assert str(e2) == "('a', 'b', 'c')" # if "super()..." part above is commented out, this assertion will not pass, because str(e2) is an empty string
Answers:
The implementation of BaseException.__str__
, which you inherit if you don’t otherwise define a __str__
method, only considers the "args" tuple (src). If you pass through as keyword arguments then the "args" will be empty.
Note: it is not necessary to call super().__init__
for custom exception types, unless you need your type to work in cooperative multiple inheritance.
That’s because the exception args attribute, which BaseException.__str__
uses to render the error as a string, is set by the __new__
method.
Can someone clarify the role of super().__init__(a, b, c)
in making the second assertion pass? It will fail without it (empty string is returned from str
).
Per my understanding Exception
is a built-in type that takes no keyword arguments.
But what exactly is happening in Exception
when the super().__init__(a, b, c)
is called?
Can calling init
like that have some unwanted side-effects?
class MyException(Exception):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
super().__init__(a, b, c)
e1 = MyException('a', 'b', 'c')
assert str(e1) == "('a', 'b', 'c')"
e2 = MyException(a='a', b='b', c='c')
assert str(e2) == "('a', 'b', 'c')" # if "super()..." part above is commented out, this assertion will not pass, because str(e2) is an empty string
The implementation of BaseException.__str__
, which you inherit if you don’t otherwise define a __str__
method, only considers the "args" tuple (src). If you pass through as keyword arguments then the "args" will be empty.
Note: it is not necessary to call super().__init__
for custom exception types, unless you need your type to work in cooperative multiple inheritance.
That’s because the exception args attribute, which BaseException.__str__
uses to render the error as a string, is set by the __new__
method.