Chapters
Python114 chapters

Classes and objectsChapter 62 of 114

Methods

Functions that belong to a class, and the three kinds of them.

A method is a function on a class

Python
class Dog:
    def __init__(self, name):
        self.name = name
        self.tricks = []

    def learn(self, trick):
        self.tricks.append(trick)

    def show(self):
        return f"{self.name} knows: {', '.join(self.tricks)}"

rex = Dog("Rex")
rex.learn("sit")
rex.learn("roll")
print(rex.show())

Output

Rex knows: sit, roll

rex.learn("sit") passes rex as self automatically. That is the whole trick of method calls.

Methods can call each other

Through self, a method can use anything else on the object:

Python
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

    def describe(self):
        return f"{self.width}x{self.height}, area {self.area()}"

print(Rectangle(3, 4).describe())

Output

3x4, area 12

Forgetting self. is the common slip. A bare area() looks for a plain function of that name and raises NameError.

Returning versus changing

A method can change the object, return a value, or both. Be clear which:

Python
class Counter:
    def __init__(self):
        self.value = 0

    def bump(self):
        self.value += 1

    def doubled(self):
        return self.value * 2

c = Counter()
c.bump()
print(c.value, c.doubled())

Output

1 2

Returning self lets calls chain, which some libraries use heavily:

Python
class Query:
    def __init__(self):
        self.parts = []

    def where(self, clause):
        self.parts.append(clause)
        return self

    def build(self):
        return " AND ".join(self.parts)

print(Query().where("a = 1").where("b = 2").build())

Output

a = 1 AND b = 2

classmethod

Takes the class rather than an instance. The main use is an alternative way to build one:

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

    @classmethod
    def puppy(cls, name):
        return cls(name, 0)

rex = Dog.puppy("Rex")
print(rex.name, rex.age)

Output

Rex 0

cls is the class, so cls(name, 0) builds one. Using cls rather than Dog means a subclass gets its own type back.

staticmethod

Takes neither. It is a plain function that lives in the class because it belongs there conceptually:

Python
class Temperature:
    @staticmethod
    def c_to_f(celsius):
        return celsius * 9 / 5 + 32

print(Temperature.c_to_f(100))

Output

212.0

If it never touches self or cls, it can be a staticmethod — or, just as often, a module-level function.

property

Makes a method look like an attribute. Use it for a value derived from others:

Python
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    @property
    def area(self):
        return self.width * self.height

r = Rectangle(3, 4)
print(r.area)
r.width = 10
print(r.area)

Output

12
40

No brackets on r.area, and it recalculates. Storing self.area in __init__ instead would have gone stale the moment width changed.

A setter adds validation without changing how callers write it:

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

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if value < 0:
            raise ValueError("age cannot be negative")
        self._age = value

rex = Dog(3)
rex.age = 4
print(rex.age)

try:
    rex.age = -1
except ValueError as problem:
    print("ValueError:", problem)

Output

4
ValueError: age cannot be negative

Test yourself

2 questions

What does @property let you do?

Show the answer

Call a method without brackets, like an attribute — It is how a derived value stays correct when the values it depends on change.

What does a classmethod receive as its first argument?

Show the answer

The class — Using cls(...) rather than the class name by hand means a subclass gets its own type back.

Next chapter

self

What self actually is, and why you have to write it.