Contact
Evil Genius SocietyHomeLearnForumLeaderboardSocialsMessages
← Back to module

Lesson 2 of 11

Setting attributes from outside the class is unreliable. The __init__ method fixes that: it runs automatically every time you create an object, so every instance is set up properly from birth.

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

rex = Dog("Rex", "Labrador")
print(rex.name)
print(rex.breed)

Note you never call __init__ yourself — writing Dog("Rex", "Labrador") calls it for you, and the arguments go straight to its parameters.

Dunder methods

__init__ has double underscores on both sides. Python calls these dunder (double underscore) methods, and they're how your class hooks into built-in behaviour. __init__ hooks into object creation. You'll meet several more in this module.

What is self?

self is the object being worked on. It is always the first parameter of a method, and Python passes it automatically.

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

rex = Dog("Rex")
fido = Dog("Fido")

print(rex.name)
print(fido.name)

When you write Dog("Rex"), Python creates a blank object and passes it in as self. So self.name = name means "store this name on this particular object." That's why rex and fido don't interfere — each call had a different self.

The name self is only a convention, but it is a universal one. Use it.

self.name = name

This line confuses people at first. There are two different things here:

  • name (right side) — the parameter, a local variable that vanishes when __init__ ends.
  • self.name (left side) — an attribute stored on the object, which lives as long as the object does.

They happen to share a name because that reads well. You could write self.name = n and it would work identically.

Forget the self. and the value is silently lost:

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

rex = Dog("Rex")
print(rex.name)

That raises AttributeError: 'Dog' object has no attribute 'name' — nothing was ever stored.

Defaults and computed attributes

__init__ is an ordinary function, so default parameters work, and you can compute attributes that weren't passed in:

class Dog:
    def __init__(self, name, age=0):
        self.name = name
        self.age = age
        self.is_puppy = age < 1

print(Dog("Rex", 3).is_puppy)
print(Dog("Fido").is_puppy)

Try it yourself

Write a Book class whose __init__ takes a title, author, and pages.

Checkpoint

  • __init__ runs automatically when an object is created.
  • self is the object itself, always the first parameter, passed automatically.
  • self.x = x stores a value on the object; without self. it's just a local.
  • __init__ guarantees every instance starts with the attributes it needs.

Questions about this lesson

Log in to ask a question.