livepython.net
CHAPTER 20Object-Oriented Programming (Classes)
20.2  __INIT__

Python __init__ Method, self and Attributes

The __init__ Method in Python

The __init__ method is a special function inside a class that Python runs automatically every time you make an object. Its job is to give the new object its starting attributes. "init" is short for "initialize", a fancy word for "set up at the start".

Think of it like the check-in desk of a hotel. Every guest who arrives goes through it, and each one leaves with a name on the list, a room number and a key. No guest is forgotten.

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

rocky = Dog("Rocky", 3)
lucky = Dog("Lucky", 5)
print(rocky.name, rocky.age)
print(lucky.name, lucky.age)
OUTPUT
Rocky 3
Lucky 5

The rules

  • Write it inside the class, indented, with def: def __init__(self, name, age):
  • Two underscores before init and two after. Names with this shape are special: Python calls them for you. Programmers call them "dunder" methods, from "double underscore".
  • The values in Dog("Rocky", 3) go to the parameters after self, in order, like the arguments of a function in chapter 15.
  • You never call __init__ yourself. Dog("Rocky", 3) calls it.

Before and after

By hand (last topic)With __init__
rocky = Dog(), then rocky.name = "Rocky", then rocky.age = 3rocky = Dog("Rocky", 3)
easy to forget an attributeevery object gets every attribute

Avoid: forgetting an argument

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

rocky = Dog("Rocky")
OUTPUT
TypeError: Dog.__init__() missing 1 required positional argument: 'age'

Don't be scared of this error! It's the same as calling a function with a missing argument: __init__ needs a name and an age, and it only got a name.

Common mistake: writing _init_, with one underscore on each side. Python doesn't see it as the setup method, so it never runs, and Dog("Rocky", 3) fails with TypeError: Dog() takes no arguments.

__init__ runs by itself each time you make an object, and gives it its starting attributes.

your turnPredict the output

What will this print?

class Player: def __init__(self, name, score): self.name = name self.score = score p = Player("Sunny", 10) print(p.score)
Your turn! What will this code show on the screen?
your turnPick the right idea

When does __init__ run?

Think about it, then pick one.

What Is self in Python?

self is the first parameter of every method in a class. It stands for the object itself: the one being set up or used right now. Python fills it in for you.

Think of it like the word "my" on a form: "My name: ..., my age: ..." Everyone fills in the same form, but "my" means a different person each time. When Rocky is being made, self is Rocky. When Lucky is being made, self is Lucky.

PYTHONedit me
class Dog:
    def __init__(self, name):
        self.name = name
        print("Made a dog called", self.name)

rocky = Dog("Rocky")
lucky = Dog("Lucky")
print(rocky.name)
OUTPUT
Made a dog called Rocky
Made a dog called Lucky
Rocky

Reading self.name = name

PartMeans
self.namethe attribute name of this object. It stays with the object.
namethe parameter: the value passed in, like "Rocky"

They often share a name, but they're different things. The parameter is gone when __init__ ends: it's a local variable (chapter 15). The attribute lives on inside the object.

  • self is always the first parameter. You don't pass it: Dog("Rocky") sends one value, and Python adds the object as self.
  • Inside the class, write self. before every attribute.
  • self is only a name, but every Python programmer uses it. Always use self.

Avoid: forgetting self in the def

PYTHONedit me
class Dog:
    def __init__(name):
        self.name = name

rocky = Dog("Rocky")
OUTPUT
TypeError: Dog.__init__() takes 1 positional argument but 2 were given

"2 were given"? Yes: "Rocky", plus the object that Python passes in on its own. With no self in the def, there's no room for both.

Avoid: forgetting self. on the attribute

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

rocky = Dog("Rocky")
print(rocky.name)
OUTPUT
AttributeError: 'Dog' object has no attribute 'name'

name = name only makes a local variable, which vanishes when __init__ ends. Nothing was stored in the object.

self is the object itself. Write self.attribute = value to store data inside it.

your turnFill the gap

Complete the __init__ method

class Cat: def __init__(?, name): self.name = name lucky = Cat("Lucky") print(lucky.name)

It should print: Lucky

Which piece makes this code work?
your turnPick the right idea

In self.name = name, which part is still there after __init__ ends?

Think about it, then pick one.

Read and Change Object Attributes

An attribute is a variable that belongs to one object. Read it with a dot, like sunny.balance, and change it with =, just like any variable.

Think of it like the cards at a vet's clinic. Every pet has a card with the same boxes: name, age, weight. But each card holds its own values, and the vet can update Rocky's weight without touching Lucky's card.

PYTHONedit me
class Account:
    def __init__(self, owner, balance):
        self.owner = owner
        self.balance = balance

sunny = Account("Sunny", 100)
rocky = Account("Rocky", 500)
sunny.balance += 50
print(sunny.owner, sunny.balance)
print(rocky.owner, rocky.balance)
OUTPUT
Sunny 150
Rocky 500

The rules

  • object.attribute reads a value: print(sunny.balance).
  • object.attribute = value changes it. += and -= work too, as in chapter 5.
  • Each object has its own attributes. Adding 50 to Sunny's balance leaves Rocky's alone.
  • Attributes can hold any value: numbers, strings, lists, even other objects.
  • Use an attribute anywhere you'd use a variable: in an if, a loop or an f-string.
PYTHONedit me
class Student:
    def __init__(self, name, marks):
        self.name = name
        self.marks = marks

lucky = Student("Lucky", 72)
if lucky.marks >= 40:
    print(f"{lucky.name} passed with {lucky.marks}")
OUTPUT
Lucky passed with 72

Avoid: a typo in the attribute name

PYTHONedit me
class Student:
    def __init__(self, name, marks):
        self.name = name
        self.marks = marks

lucky = Student("Lucky", 72)
print(lucky.mark)
OUTPUT
AttributeError: 'Student' object has no attribute 'mark'

Every error is a clue! Python looked inside lucky for mark and found only name and marks. Check the spelling against __init__.

Common beginner doubt: "Can I add a new attribute later, outside the class?" Python allows it, as you saw in the last topic. But it's better to create every attribute in __init__. Then all objects of a class have the same attributes, and a reader finds them all in one place.

Read an attribute with a dot, change it with =. Each object keeps its own values.

your turnSpot the bug

Which line breaks?

One line stops this program. Tap it.
your turnPredict the output

What will this print?

class Account: def __init__(self, owner, balance): self.owner = owner self.balance = balance a = Account("Sunny", 100) b = Account("Rocky", 100) a.balance -= 30 print(a.balance, b.balance)
Your turn! What will this code show on the screen?

Default Attribute Values in __init__

Not every attribute needs an argument. An attribute can start with a default value: either a parameter default, as you learned in chapter 15, or a fixed value set right inside __init__.

Think of it like opening a new bank account. You give your name, and the bank fills in the rest: the balance starts at 0, and the history of payments starts empty.

PYTHONedit me
class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self.balance = balance
        self.history = []

sunny = BankAccount("Sunny")
rocky = BankAccount("Rocky", 500)
print(sunny.owner, sunny.balance, sunny.history)
print(rocky.owner, rocky.balance, rocky.history)
OUTPUT
Sunny 0 []
Rocky 500 []

Two kinds of defaults

You writeWhen to use it
balance=0 in the def linethe caller may pass a value; if not, it's 0
self.history = [] in the bodyevery new object starts the same; the caller can't choose
  • Parameters with defaults go last, as in chapter 15.
  • self.history = [] runs for each new object, so each account gets its own empty list.
  • Keyword arguments work too: Player("Lucky", lives=5).
PYTHONedit me
class Player:
    def __init__(self, name, lives=3):
        self.name = name
        self.lives = lives
        self.score = 0

rocky = Player("Rocky")
rocky.score += 10
rocky.lives -= 1
lucky = Player("Lucky", lives=5)
print(rocky.name, rocky.lives, rocky.score)
print(lucky.name, lucky.lives, lucky.score)
OUTPUT
Rocky 2 10
Lucky 5 0

Rocky lost a life and scored 10 points. Lucky started with 5 lives and still has a score of 0.

Avoid: a default before a required parameter

PYTHONedit me
class Player:
    def __init__(self, lives=3, name):
        self.name = name
        self.lives = lives
OUTPUT
SyntaxError: parameter without a default follows parameter with a default

The same rule as any function: parameters without a default come first, then the ones with a default.

Give an attribute a starting value with a parameter default, or set it right inside __init__.

your turnFix the code

Fix the code so it prints: Sunny 0

It should print: Sunny 0

class Account:
    def __init__(self, owner, balance):
        self.owner = owner
        self.balance = balance

sunny = Account("Sunny")
print(sunny.owner, sunny.balance)
This code does not work yet. Fix it, then press Run.
your turnType the output

Remember default values in functions?

def greet(name, greeting="Hi"): return greeting + " " + name print(greet("Lucky")) print(greet("Rocky", "Hello"))
Read the code line by line, then type the output exactly.

Practice: __init__

Solve these to lock in what you learned in this topic. Each one runs in your browser.

  1. 182.Python Program to Make a Student Class with __init__EasySolve
  2. 183.Python Program to Track a Game Character's HealthMediumSolve