Start learning free

LESSON 178 OF 344 · OBJECT-ORIENTED PROGRAMMING

Constructors in Python: The __init__ Method

Lesson Read the full explanation

TL ; DR:

  • The __init__ method is Python's constructor — it runs automatically when you create an object, and it's where you set up the object's attributes.


  • The first parameter is always self (the object being created), followed by whatever arguments you want to accept:

    class Dog:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    

  • Then create objects with arguments: Dog("Rex", 4) — the __init__ method fills in the attributes for you.



Full lesson:

In the previous lesson you set attributes one at a time after creating the object:

dog = Dog()
dog.name = "Rex"
dog.age = 4

That works, but it's verbose and easy to forget. The __init__ method lets you initialize the attributes the moment Dog(...) is called.


Defining __init__

Two things are special about Python's constructor:

  • It's named __init__ (with two underscores on each side — these are called "dunders").

  • Its first parameter is self, which Python automatically passes when you create an object. self refers to the object being created.

class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age

Inside __init__, self.name = name means "store the parameter name as an attribute on this new object".


Calling the constructor

Once you've defined __init__ with arguments, every Dog(...) call must provide them:

rex  = Dog("Rex", 4)
luna = Dog("Luna", 7)

You don't pass self when calling — Python provides it for you. By the time these lines finish, rex.name is already "Rex", rex.age is 4, and the same for Luna.


Your task

Inside the Dog class, define an __init__ method that takes self, name, and age, and assigns the parameters to attributes using self.. Then below the class, create two dogs:

rex  = Dog("Rex", 4)
luna = Dog("Luna", 7)

Expected output:

Rex is 4
Luna is 7
STEP 1 OF 2
    Ctrl + Enter to check

    PYTHON · OBJECT-ORIENTED PROGRAMMING

    Constructors in Python, explained

    Why a constructor

    Without a constructor, you create an object and then fill it in line by line:

    dog = Dog()
    dog.name = "Rex"
    dog.age = 4
    

    That works, but it is wordy and easy to forget a line. If one dog never gets its age, the error shows up much later, when something reads it. Python's constructor, the __init__ method, sets the attributes in the same step that creates the object.

    Defining __init__

    Two things are special about it:

    • The name is __init__, with two underscores on each side. Python programmers call names like this "dunders", short for double underscores. Python calls the method automatically; you do not call it yourself.
    • The first parameter is self. It is the object being set up, and Python passes it in for you.
    class Dog:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    

    The line self.name = name reads as "store the parameter name as an attribute called name on this object". The two names are unrelated: the left one is an attribute of the object, the right one is the local parameter. They are often the same word, which is a convention and not a requirement.

    Calling the constructor

    You pass the arguments when you create the object, after the class name, and leave self out:

    rex = Dog("Rex", 4)
    luna = Dog("Luna", 7)
    print(rex.name, rex.age)
    print(luna.name, luna.age)
    
    Rex 4
    Luna 7
    

    Python does the following for Dog("Rex", 4): it creates an empty Dog object, then calls __init__ with that object as self, followed by "Rex" and 4. By the time the line finishes, the attributes are in place.

    The lesson's exercise

    The starter code has a Dog class with only pass in it, and two print lines at the bottom that read name and age from rex and luna. The task is to give Dog a constructor and then create the two dogs.

    1. Replace pass with the constructor. Write def __init__(self, name, age): inside the class, indented one level.
    2. Assign the attributes. In the body, write self.name = name and self.age = age, indented one level further.
    3. Create the dogs. Below the class, write rex = Dog("Rex", 4) and luna = Dog("Luna", 7).

    The final code builds each message by joining strings. The age is a number, so it goes through str() first:

    class Dog:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    rex = Dog("Rex", 4)
    luna = Dog("Luna", 7)
    print(rex.name + " is " + str(rex.age))
    print(luna.name + " is " + str(luna.age))
    
    Rex is 4
    Luna is 7
    

    What else a constructor can do

    The constructor is ordinary code, so it can do more than copy parameters. It can check its inputs, tidy them up, or create attributes that no argument supplies:

    class Dog:
        def __init__(self, name, age):
            if age < 0:
                raise ValueError("age cannot be negative")
            self.name = name.strip().title()
            self.age = age
            self.tricks = []
    
    d = Dog("  rex ", 4)
    print(d.name, d.tricks)
    
    Rex []
    

    Here the name is cleaned up, a bad age is rejected before the object is finished, and every dog starts with its own empty tricks list. The lesson's exercise only needs the plain assignments, but this is why a constructor is a better place for setup than lines scattered after the call.

    Gotchas

    Every call must supply the arguments

    Once __init__ asks for name and age, a call without them fails:

    Dog("Rex")
    
    TypeError: Dog.__init__() missing 1 required positional argument: 'age'
    

    If you want an argument to be optional, give the parameter a default value, as in def __init__(self, name, age=1):. Then Dog("Rex") works and the age is 1.

    Forgetting self.

    This version looks plausible but stores nothing:

    class Bad:
        def __init__(self, name):
            name = name
    

    The assignment only rebinds the local parameter. The object ends up with no attribute, and reading .name later raises an AttributeError.

    Returning a value

    The constructor must not return anything other than None. A return 5 inside __init__ raises a TypeError when the object is created. Its job is to set up the object, not to produce a result.

    Misspelling the name

    Python only calls a method named exactly __init__. A method called _init_ or init is just an ordinary method, and the object is created without any setup.

    Key takeaways

    • __init__ is Python's constructor. It runs automatically when you create an object.
    • Its first parameter is self, the new object. You do not pass it when calling the class.
    • Assign attributes with self.name = name, so they belong to the object.
    • The arguments in Dog("Rex", 4) go to the parameters after self.
    Keep going with PythonAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free