Reference · module 16
Classes
Everything this module explains, on one page.
Your own type
Read a class definition and know what happens when it is called.
- A class describes a kind of thing; calling it makes one. class Dog: names the kind, and Dog() builds a dog. The same split as def and a call: one defines, the other runs.
- __init__ runs at that moment and fills the new object in. Its first parameter is self, which is the object being built, and everything you attach to self stays with it.
- What you attach is an attribute, and you read it back through a dot: dog.name. A dict does much the same job with dog["name"] — the difference is that a class also carries behaviour.
The mistake you are about to make
dog = Dog
dog = Dog()
Without the brackets that is the class itself, not a dog — the same way a function without brackets stays a function. Nothing raises, so it surfaces later at the first dog.name.
Methods
Write a method and understand where its first argument comes from.
- A method is a function written inside a class. Its first parameter is self, and Python fills it in for you: d.bark() calls bark with d as self.
- That is why the definition has one more parameter than the call. def bark(self) is called as d.bark(), and def rename(self, name) as d.rename("Bo").
- Through self a method reaches the object's own attributes, and that is the whole point of a class: the data and the code that works on it travel together.
The mistake you are about to make
def bark():
def bark(self):
The call d.bark() has empty brackets, so the definition looks like it should too. Python passes the object anyway: TypeError, bark takes 0 positional arguments but 1 was given.
How an object prints
Make your object readable when it lands in a print or a list.
- Printing your own object gives something like <__main__.Dog object at 0x7f…>. That is Python saying it has no idea how you want this shown, and falling back on the type and the address.
- __repr__ is where you answer that. Define it to return a string, and print uses it. Aim it at yourself debugging at two in the morning, not at the end user.
- It pays off most inside containers. Printing a list of objects prints each one with __repr__, and a list of ten addresses is exactly as useful as no output at all.
The mistake you are about to make
print(dog) → <__main__.Dog object at 0x7f…>
def __repr__(self): return f"Dog({self.name})"
The address looks like a breakage and nothing is broken: nobody said how this object should be shown. Until somebody does, any list of your objects is unreadable.
When you do not need a class
Choose between a dict, a function and a class without ceremony.
- A class that only holds data and has no methods is a dict with extra steps. If all you need is a name and an age together, a dict says that in one line.
- A class that has one method and holds no state is a function with extra steps. Building an object in order to call one thing on it is ceremony, not design.
- A class earns its keep when data and behaviour belong together and there is more than one of each: several methods working on the same attributes, and several objects alive at once.
The mistake you are about to make
class Formatter: def format(self, text): …
def format(text): …
A class looks like the grown-up choice, so the first thing written is a class with one method. It holds no state, so there is no object: it is a function made to introduce itself.
Reading somebody else's class
Work out what an unfamiliar class does without reading every line of it.
- Start at __init__. It lists what the object is made of and what you have to supply to build one — which is most of what you needed to know before touching anything else.
- Then read the method names and skip the bodies. The names are the verbs: what this thing can be asked to do. Bodies matter only once you know which one you want.
- You can also ask the object itself. dir(x) lists its names and help(x) prints the docstrings, so a class you have in front of you never needs to be guessed at.
The mistake you are about to make
help(dog.bark())
help(dog.bark)
The brackets come along out of habit. With them you run the method first and then ask for help on the result, usually None. Ask about the method itself, without calling it.