Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does parent of custom exception class get the arguments if I don't call super().__init__()?

Suppose I create a custom exception class like this:

class MyError(Exception):
    def __init__(self, msg):
        pass

raise MyError('this is an error')

# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# __main__.MyError: this is an error

The MyError class doesn't call super().__init__(), so I don't see any way for the parent class to learn the error message ('this is an error'). Nevertheless, this code works correctly: the error message is indeed stored somewhere in the object and printed when I raise the exception.

How and why is this done? I would expect the parent class to know nothing about the error message if I override __init__() in the child class and don't call super().__init__(). I tried to find Python code for the Exception class, but it looks like it's in C and I was reluctant to dive in and figure it out.

like image 452
Matthias Fripp Avatar asked Apr 14 '21 20:04

Matthias Fripp


People also ask

What is the parent class of any custom exception?

In order to create custom exception, we need to extend Exception class that belongs to java.lang package.

How do I raise a custom exception?

Steps to create a Custom Exception with an Example Create one local variable message to store the exception message locally in the class object. We are passing a string argument to the constructor of the custom exception object. The constructor set the argument string to the private string message.

How do you define a custom exception type in Python?

In Python, users can define custom exceptions by creating a new class. This exception class has to be derived, either directly or indirectly, from the built-in Exception class. Most of the built-in exceptions are also derived from this class.

What is the advantage of creating your own custom exception class?

The big advantage is that it allows you to throw and exceptions that mean what you want them to mean. If you reuse an existing exception, any piece of your code that catches the exception has to deal with possibility that the actual exception wasn't thrown by your code, but by some other library party code.


1 Answers

It's kind of weird. BaseException implements both __new__ and __init__, and sets self.args in both methods. Most classes only implement one or the other. You only overrode __init__, so __new__ still receives the arguments.

If you overrode __new__ and prevented the arguments from reaching BaseException.__new__, you'd find the message is lost:

class MyError(Exception):
    def __init__(self, msg):
        pass
    def __new__(cls, msg):
        return super().__new__(cls)
like image 103
user2357112 supports Monica Avatar answered Oct 04 '22 01:10

user2357112 supports Monica