30% off your first 3 months

Get the deal

Classes and objects in plain words

by DuckyHelperNov 12, 20264 min read
Computer science

TL;DR:

  • A class is a blueprint. An object (or instance) is one thing built from it, with its own data.

  • Attributes are the data an object stores. Methods are the functions that belong to the class and work on that data.

  • Classes keep related data and behaviour together, so a program can model many similar things without copying code.

A program that tracks pets needs a name and an age for each pet, and ways to make each pet do things. You could keep separate variables for every pet, but that gets out of hand quickly. A class lets you describe 'a dog' once and then make as many dogs as you like.

The idea in plain words

A class is a blueprint that says what data something has and what it can do. An object, also called an instance, is one actual thing built from the blueprint. The data stored in an object are its attributes. The functions defined in the class are its methods.

The cookie cutter is the class and each cookie is an object. All cookies share a shape, but each one can have different icing.

Why programmers use classes

  • Keep related things together. A dog's name, age and actions live in one place.

  • Reuse. Write the blueprint once, make many objects.

  • Hide detail. Other code can say rex.bark() without knowing how barking works inside.

  • Model the real world. A program about a game, a school or a shop is easier to think about as objects.

Worked example: a Dog class with a bark method

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

    def bark(self):
        return f"{self.name} says woof!"

    def birthday(self):
        self.age += 1

rex = Dog("Rex", 3)
luna = Dog("Luna", 5)

print(rex.bark())
rex.birthday()
print(rex.age)
print(luna.age)

Read it from the top.

  1. class Dog: starts the blueprint.

  2. __init__ is a special method that runs when you create a new dog. It receives the values and stores them as attributes on the new object. The first parameter, self, stands for the object being built.

  3. self.name = name saves the name inside that dog. Each dog has its own copy.

  4. bark is a method. It uses self.name to say who is barking and returns a string.

  5. birthday is a method that changes the object: it adds 1 to that dog's age.

Now trace the program. Dog('Rex', 3) builds one object with name Rex and age 3, and Dog('Luna', 5) builds a second with name Luna and age 5. They share the blueprint but not the data.

Line

What happens

Output

print(rex.bark())

Calls bark on rex, so self.name is Rex

Rex says woof!

rex.birthday()

rex.age goes from 3 to 4

(none)

print(rex.age)

Reads rex's age

4

print(luna.age)

Reads luna's age, untouched

5

The last line shows the main point: changing Rex did not change Luna. Each instance carries its own attributes.

Many objects, one loop

Because every dog has the same attributes, you can keep several in a list and treat them alike.

dogs = [Dog("Rex", 3), Dog("Luna", 5), Dog("Bo", 1)]

total_age = 0
for d in dogs:
    print(d.name, d.age)
    total_age += d.age

print(total_age)

This prints Rex 3, Luna 5, Bo 1 and then 9, since 3 + 5 + 1 = 9. Notice that the loop never needs to know how a dog is built. It only uses the attributes.

What self really is

When you write rex.bark(), Python quietly turns it into a call of the class's bark function with rex passed as the first argument. Inside the method, self is just a name for that object. That is how the same method can say Rex's name for one dog and Luna's name for another: the code is shared, and self points to the dog it was called on.

It also explains the usual error. If you write def bark(): without self, Python still passes the object in, finds no parameter to receive it, and complains that the method takes 0 arguments but 1 was given.

Methods that take extra information

A method can take parameters after self, just like a function. If you add a rename method, def rename(self, new_name): with the body self.name = new_name, then rex.rename("Max") changes Rex's name to Max, and rex.bark() returns Max says woof!. The object remembers the new name, because the attribute lives inside it.

How to check your answer

  • Can you point at the class, an object, an attribute and a method in the code?

  • For each line, can you say which object's data it reads or changes?

  • Check that the printed outputs match your trace: Rex says woof!, 4, 5.

  • Create a third dog and confirm it starts with its own values.

Common mistakes

  • Forgetting self as the first parameter of a method, which causes a TypeError about the number of arguments.

  • Forgetting self. when reading an attribute inside a method, which gives a NameError.

  • Mixing up the class and an object: Dog is the blueprint, rex is a dog.

  • Writing __init__ with a single underscore on each side, so it never runs.

  • Expecting changes to one object to affect another.

Where you will use it next

Classes appear throughout Python libraries and in languages like Java and C++. A graph node, a bank account, a game character and a contact in an app can each be a class. To see how the computer actually runs methods like these, read how a computer runs your code.

Frequently asked questions

Is a class the same as a function?

No. A function is one piece of behaviour. A class bundles data together with several functions that work on it.

Do I always need classes?

No. Small programs often work fine with functions and dictionaries. Classes pay off as programs grow.

Get started

DuckyHelper can
do more

It sees your screen and works in any app you use. Try it for 10 minutes, no card.

Get it for Mac, Windows or Linux

Share

Questions and jobs

Do anything

Ask it a question or hand it a job, in any app.

Doing jobs for you is in early access on Mac. Asking works on Mac, Windows and Linux.