Objects · Lesson 13 of 18 · 20 min
Classes and instances
Attributes, self, class vs instance data, and methods.
- Construct objects with __init__
- Distinguish class attributes from instance attributes
- Use instance, class, and static methods
A class is a factory for objects
`class` creates a class object. Calling the class (`Point(1, 2)`) creates an instance. `__init__` is not the constructor — `__new__` allocates — but `__init__` is where you attach attributes to `self`. By convention every instance method takes `self` as the first parameter; the call `p.distance()` binds `p` to `self`.
Attributes live on the instance dict (`p.__dict__`) unless you use slots. Lookup walks the instance, then the class, then base classes. Assignment `self.x = 1` always writes to the instance (unless a data descriptor sits in the way).
class Point:
origin_count = 0
def __init__(self, x, y):
self.x = x
self.y = y
if x == 0 and y == 0:
Point.origin_count += 1
def distance(self):
return (self.x ** 2 + self.y ** 2) ** 0.5
@classmethod
def origin(cls):
return cls(0, 0)
@staticmethod
def polar(r, label):
return f"{label}:{r}"
p = Point(3, 4)
print(p.distance(), Point.origin_count)
print(Point.origin().x, Point.polar(1, "N"))Three kinds of method
| Decorator | First arg | Use |
|---|---|---|
| (none) | self — the instance | Reads/writes instance state |
| @classmethod | cls — the class | Alternate constructors |
| @staticmethod | none | A function namespaced on the class |
Representation and equality
Default equality for user classes is identity. If your object is a value, define `__eq__` and `__hash__` together — or set `__hash__ = None` if it is mutable. `__repr__` should look like a constructor call so logs are readable.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point({self.x}, {self.y})"
def __eq__(self, other):
return isinstance(other, Point) and (self.x, self.y) == (other.x, other.y)
print(Point(1, 2))
print(Point(1, 2) == Point(1, 2))
print(Point(1, 2) == (1, 2))Check yourself
Quiz
1.`p.distance()` is equivalent to:
2.@classmethod is the right tool for:
3.User classes compare with == by default using:
Practice
Exercise
Write a class `Counter` with `__init__(self, start=0)`, methods `inc(self, n=1)` and `dec(self, n=1)`, and a read-only-feeling `value()` method that returns the current count. `dec` should not go below 0.
Tutor
Ask a question about this lesson. Answers are generated on demand and capped so the session stays focused.