A method in Python: the function attached to an object

A method is a function defined inside a class and attached to an object. The role of self, the four families, and the calling traps.
6 min read
Believemy logo

Definition

Picture a function whose job is to total up a shopping basket. It needs to know what is inside the basket, so the basket gets passed in as an argument. The trouble starts once several functions share that same basket: each one asks for the same information, and a single missed parameter introduces a bug that does not show up just by reading the code.

A method answers that annoyance by attaching the function to the object. It is a function defined inside a class and attached to its objects, written with the same def as an ordinary function: its first parameter receives the calling object and by convention it is named self.

Here is what that looks like once it sits inside a class.

PYTHON
class Basket:
    def __init__(self):
        self.items = []

    def add(self, item):
        self.items.append(item)

basket = Basket()
basket.add("keyboard")

Look at the mismatch between the declaration and the call: add expects two parameters, self and item, yet only one is supplied. The dot in front of add does the missing work, telling Python which object should fill self. basket.add("keyboard") is exactly the same as Basket.add(basket, "keyboard"), nothing more.


What attaching the function to the object changes

Why bother with this detour instead of sticking to ordinary functions? The answer comes down to memory: a function receives its data on every call, a method lives with it permanently, in the form of the object attributes. It reads and changes every attribute of its object without an extra argument.

Compare the two versions below to see it for yourself.

PYTHON
# Without a method: every function asks for the same arguments
def add(items, item):
    items.append(item)

def total(items, prices):
    return sum(prices[i] for i in items)

# With a method: the data is already attached to the object
class Basket:
    def add(self, item):
        self.items.append(item)

On a thirty-line script the first form is plenty. The difference is felt as soon as the same bundle of data travels between several functions, where a swapped parameter goes unnoticed until it breaks something. The method keeps everything about the basket in one place, which makes calling mistakes nearly impossible. It is a matter of organisation first, and only then a matter of technique.


The four families of methods

Not every method receives self the same way, and that is exactly what sorts them into four families, summed up in the table below.

FamilyFirst parameterWhat it is for
Instance methodself, the objectRead or change one specific instance
classmethodcls, the classBuild an object other than through __init__
staticmethodNoneKeep a helper next to the class that uses it
magic methodself, the objectGive native behaviour: addition, display, length

The first family covers most of what gets written day to day, and a beginner who knows nothing but the instance method already writes correct code. The next two are easy to spot, thanks to the at sign above the def. The last one is recognised by its two pairs of underscores, like __init__, and wires an object into Python native operators.


The trap of the method that returns nothing

A classic annoyance turns up when methods get chained as though they were ordinary functions. Many standard library methods change the object in place and hand back None, because the object has already been changed and there is nothing more to give back.

PYTHON
names = ["zoe", "adam", "lea"]

# Sorts the list in place and returns None: nothing to catch here
result = names.sort()

# Builds a brand new sorted list, leaving the original untouched
result = sorted(names)
Warning

The bug that follows never fires on the names.sort() line itself. It waits a line further down, when an AttributeError reports that None has no such method.

Keep one simple rule in mind: whatever acts on the object in place returns None, whatever builds a result hands it back. sort() sorts the existing list without handing anything back, sorted() builds a new list and returns it.


Redefining an inherited method

What happens when a child class needs to behave almost like its parent, but not quite? It receives its parent methods through inheritance and may rewrite one under the same name.

PYTHON
class Customer:
    def discount(self):
        return 0

class LoyalCustomer(Customer):
    def discount(self):
        return super().discount() + 10

Python always keeps the version closest to the object: if LoyalCustomer defines its own discount method, that is the one that runs, never the one from Customer. To avoid copying out what the parent class already does, super makes it possible to call its version from the child class and add only what is missing.

This is where a method really parts ways with an ordinary function. Its name no longer points at a fixed block of code, but at the block the object carries with it. Two different objects, called through the same line object.discount(), run two different bodies, and the calling code never needs to know which one fires.


Frequently asked questions

Question

What is the difference between a method and a function?

A function stands alone and receives everything it needs as arguments. A method belongs to a class and additionally receives the object it is called on, which grants it access to that object state without an extra parameter.

Question

Does self really have to be written in every definition?

Yes, for an instance method. Python supplies it automatically at call time, but it does not appear on its own in the signature: writing it in is up to you. Leaving it out produces an error about the number of arguments, always one more than expected, and it is often the very first mistake beginners run into.

Question

How can the methods of an object be listed?

The dir(object) function gives the complete list, underscores included, and help(object) adds the explanations written by the author of the class. Our Python course covers classes once functions are firmly in place, because a method only makes sense at that point.

Related terms

Discover our python glossary

Browse the terms and definitions most commonly used in development with Python.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.