What is __init__ in Python?

When reading over other people’s Python code, many beginners are puzzled by the __init__(self) method. What’s its purpose? This article answers this question once and for all.

What’s the purpose of __init__(self) in Python?

The reserved Python method __init__() is called the constructor of a class. You can call the constructor method to create an object (=instance) from a class and initialize its attributes.

Python __init__ method constructor

While this answers the question, if you’ve got any ambition in becoming a professional Python coder, it’s not enough to know that the __init__ method is the constructor of a class. You also need to know how to use the constructor in your own projects—and how to customize its arguments. A thorough understanding of the constructor serves as a strong foundation for more advanced concepts in object-oriented Python programming. Read on to learn the other half of the equation.

Interactive Example: Before I’ll explain it to you, let’s open your knowledge gap. Consider the following example:

Exercise: Add one argument color to the __init__ method and make the code run without error!

Let’s dive into this simple example in great detail.

How to Use the __init__ Method in Practice? A Simple Example

We’ll use some terms of object-oriented programming in Python to explain our example. Make sure to study the following cheat sheet (you can also download the PDF here). Click the image to get the cheat sheet (opens in a new tab). If you’re already comfortable with basic object-orientation terminologies like classes and instances, simply read on.

You’ve learned that the __init__ method is the constructor method of a class. You call the constructor method to create new instances (or objects). But how exactly does this play out in practice? Before we dive into the correct use, we need to understand the arguments (or parameters) of the constructor method.

The Self Argument

The __init__ constructor requires at least one argument. According to the PEP8 standard, it’s good practice to denote this argument as self. In any case, the self argument points to the newly-created instance itself and it allows you to manipulate the instance attributes of the new instance. In the dog example, you’d use self.color = "blue" to set the newly-created dog’s color attribute to the string "blue".

Let’s have a look at the following basic code example:

class Dog:

    def __init__(self):
        self.color = "blue"


bello = Dog()
print(bello.color)
# blue
  1. We create a new class Dog with the constructor __init__(self).
  2. We create a new instance of the class Dog named bello. There are two interesting observations: First, we use the class name rather than the constructor name to create the new instance. Python internally calls the __init__ method for us. Second, we don’t pass any argument when calling Dog(). Again, Python implicitly passes a reference to the newly created instance (bello) to the constructor __init__.
  3. We print the color attribute of the newly-created bello instance. The result is the string value "blue" as defined in the constructor.

However, this minimal example is unrealistic. Some dogs are brown, others are black, and only some are blue.

Multiple Constructor Arguments

So how can we create different dogs with different colors? We can easily achieve this by using more arguments, in addition to self, when defining our constructor __init__. Here’s another example where we create two dogs with different colors. Can you spot their colors?

class Dog:

    def __init__(self, color):
        self.color = color
        

bello = Dog("blue")
print(bello.color)
# blue

alice = Dog("brown")
print(alice.color)
# brown

In contrast to the first example, we now define the constructor __init__(self, color) with two arguments rather than one.

The first is the self argument as before. The second is a custom argument color that is passed through by the caller of the constructor. In our case, we create two Dog instances, bello and alice, by specifying the color argument for both.

Note that the self argument is handled implicitly by the Python programming environment: Python simply passes a reference to the respective Dog instance to the __init__ constructor.

What’s the Difference between the Constructor and the Initializer?

Well, I haven’t used a very accurate terminology in the previous paragraphs. I used the term “constructor” for both the call Dog() and the call __init__(). But only the former call can be denoted as constructor method because only this call actually creates a new instance. At the time, we call the method __init__, the instance has already been created (Python passes it to us via the self argument). That’s why a more precise term for the __init__ method is initializer method. That’s how I’ll denote it in the following to make up for it. πŸ˜‰

What’s the Meaning of the Underscores in the __init__ Method Name?

I’ve written a whole article about the meaning of the underscore in Python. Check it out if this topic interests you further. The key takeaway, however, is the following:

The double underscore β€œ__” (called β€œdunderβ€œ) is used to make an instance attribute or method private (cannot be accessed from outside the class) β€” when used as leading dunder. When used as enclosing dunder (e.g. β€œ__init__”) it indicates that it is a special method in Python (called β€œmagic method”).

How to Use __init__ in an Inherited Class?

An inherited class is a class that inherits all attributes and methods from a parent class. Here’s an example:

class Dog:
    def __init__(self, color):
        self.color = color
        

class CuteDog(Dog):
    def __init__(self, color):
        Dog.__init__(self, color)
        self.hairs = True


bello = CuteDog('brown')
print(bello.hairs)
# True

print(bello.color)
# brown

Inheritance is very important in Python. In the example, the parent class is the class Dog you already know from above. The initializer method __init__ defines the color of this dog.

Now, we also create a new class CuteDog that inherits all attributes from the parent class Dog. You can define inheritance by specifying the name of the parent class within the brackets after the child class: CuteDog(Dog).

The interesting thing is that the __init__ method of the child class CuteDog calls the __init__ method of the parent class. This makes sense because the child class has the same attributes as the parent class—and they need to be initialized, too.

The more Pythonic way, however, is to use the super() function that makes it easier for you to access the parent class:

class Dog:
    def __init__(self, color):
        self.color = color
        

class CuteDog(Dog):
    def __init__(self, color):
        super().__init__(color)
        self.hairs = True


bello = CuteDog('brown')
print(bello.hairs)
# True

print(bello.color)
# brown

With the help of the super() function, you can easily reuse the initializer method of the parent class.

Let’s have a look at a few related questions.

Is __ init __ Necessary in Python?

No. You can simply skip the initializer method. As a result, your class won’t have any instance attributes directly after its creation. However, you can add instance attributes dynamically at any future point in time. Here’s an example:

class Dog:
    None
        

bello = Dog()
bello.color = "blue"
print(bello.color)
# blue

How beautiful! You can even create empty classes and “fill in” the methods and attributes later in Python.

What Does __ init __ Return?

The __init__ method itself returns nothing. Technically, Python first uses the constructor method Dog() before it uses __init__ to initialize all attributes. Hence, only the constructor returns the newly-created instance.

Can __init__ Return a Value?

No. The only return value that doesn’t cause a runtime error is None. All other return values cause an error. See the following code example:

class Dog:

    def __init__(self, color):
        self.color = color
        return 0
        

bello = Dog("blue")
# TypeError: __init__() should return None, not 'int'

So never use any return value in the __init__ method and you’re good to go.

Where to Go from Here?

Thanks for reading through the whole article. You’ve learned that the __init__ name is reserved for the Python initializer method that is called within the constructor.

The article requires a thorough understanding of the Python basics. Investing time to learn and study those is vital for your success as a professional coder.

To help people grow their skills in an automated, personalized way, I’ve created a free Python email course “Coffee Break Python” that grows your skill level in a seemingless way. Day after day after day…

Join tens of thousands of Python coders (100% free)!

Leave a Comment