Classes and Objects

Bundling data with the functions that work on it: what a class defines, what an instance holds, and what self actually is.

classes.py

classes.py Python 3
Output

                    

class_vs_instance.py

class_vs_instance.py Python 3
Output

                    

Worth knowing

The class is the template; each ClassName(...) call builds one instance.
__init__ runs on creation and sets up the instance's own data.
self is the instance. Python passes it in; you write it as the first parameter.
Attributes on self are per object. Attributes on the class are shared by all of them.

Classes and Objects: A Practical Guide

A class bundles data with the functions that operate on it. The class is a template; each instance built from it carries its own copy of the data and shares the behaviour.

Template and instance

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

Dog describes what a dog is. Dog("rex", 3) builds one. Build two and they are independent: changing a.age leaves b.age alone, because each instance has its own attributes.

What __init__ does

__init__ runs immediately after the instance is created, and its job is to set up that instance's data. It is not a constructor in the C++ sense — the object already exists by the time it runs — but in practice it is where you put everything the object needs to start life.

The double underscores mark it as a name Python itself calls. You almost never call __init__ directly.

self is not magic

self is the instance, handed to the method as its first argument. Python does this for you: a.speak() is Dog.speak(a), and the page prints both to show they are the same call.

The name self is convention rather than syntax — the first parameter could be called anything — but every Python programmer expects self, and using something else will read as a mistake.

Every method that touches instance data needs it, and every attribute belonging to the instance is reached through it. Forgetting self. inside a method is the most common early error: you get a local variable that vanishes when the method returns.

Class attributes are shared

class Counter:
    total = 0      # one, for everybody
    def __init__(self):
        self.count = 0  # one per instance

self.count belongs to the object. Counter.total belongs to the class and every instance sees the same one. This is occasionally what you want — a registry, a shared cache, a constant — and is a bug the rest of the time, in the same family as the mutable default argument.

__repr__ earns its keep immediately

By default, printing an object gives you something like <__main__.Point object at 0x104...>, which tells you nothing. Define __repr__ and you decide:

def __repr__(self):
    return f"Point({self.x}, {self.y})"

It costs two lines and pays for itself the first time you print a list of them.

When to write one

Not for everything. If you have a function and some data it operates on, and they keep travelling together — passed to the same functions, returned in pairs — a class makes that relationship explicit. If you just need to return two values, a tuple is lighter and clearer.

Check yourself

0 of 3

Answer without scrolling back up.

  1. What is `self`?

  2. `total = 0` written directly in the class body is:

  3. You print an object and get `<__main__.Point object at 0x...>`. The fix?

Cheat sheet

Classes and Objects

A class bundles data with the functions that operate on it. The class is a template; each instance built from it carries its own copy of the data and shares the behaviour.

PYTHON · vizlearn.in/python/classes_and_objects.html

About the author

Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.