Learn

Short lessons with real code you can edit and run on the page.

Classes and Objects in Python

Lesson 28 Python 3.14 Runs in your browser
In short

A class defines a new type of object, and each object made from it is an instance of that class. The __init__ method sets up a new object's attributes, and methods are functions inside the class that receive the object as self.

Key facts

  • class Player: starts a class, and Player("Ada") creates an object from it.
  • Python runs __init__ each time you call the class to create an object, with the new object as self.
  • ada.greet() runs the same code as Player.greet(ada), so the method receives ada as its first argument.
  • An attribute set on self belongs to one object, and one set in the class body is shared by every object.
  • If a class defines neither __str__ nor __repr__, print() shows its objects as <__main__.Player object at 0x...>.

What is a class in Python?

A class defines a new type of object. It holds the code that sets up each object's data and the functions that work with that data, and you write it once with the class keyword.

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

ada = Player("Ada")
print(ada.name)
print(type(ada))
Output
Ada
<class '__main__.Player'>

Player("Ada") creates an object, and ada.name reads its name attribute, a value stored on the object. Inside the class, __init__ runs for each new object, and self.name = name stores the name on that object.

type() shows the new type in the same <class '...'> form as str in the data types lesson. __main__ is the module name Python gives the file you run.

A dictionary could hold the same name, but a class keeps the code that works on the data next to it, and its __init__ method gives every new object the same starting attributes.

PEP 8, the Python style guide, recommends CapWords for class names, such as Player or BankAccount. Built-in classes such as list and str follow a separate lowercase convention.

What is an object in Python?

An object is a single value with its own type and its own data. Every value in Python is an object, and one made from a class is also called an instance of that class.

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

ada = Player("Ada")
grace = Player("Grace")
print(ada.name, grace.name)
print(ada is grace)
print(ada == Player("Ada"))
print(isinstance(ada, Player))
Output
Ada Grace
False
False
True

Each Player() call creates a separate object with its own name. ada is grace is False because the variables ada and grace point to different objects, and isinstance() confirms that ada is a Player.

For a class you write, == works like the is operator until the class defines an __eq__ method, so two players named Ada are not equal. Lists and strings compare their contents because their classes define that method.

What does __init__ do in a Python class?

__init__ sets up each new object. Python calls it right after creating the object and passes it the arguments from the call, such as "Ada" in Player("Ada").

Python
class Player:
    def __init__(self, name, level=1):
        print("Creating", name)
        self.name = name
        self.level = level

ada = Player("Ada")
grace = Player("Grace", 3)
print(ada.level, grace.level)
Output
Creating Ada
Creating Grace
1 3

The two Creating lines show that __init__ ran once per object. Its parameters work like a function's, so level has a default and the first call leaves it out.

Python runs some methods for you, for example when you create, print or compare objects, and their names have two underscores on each side, like __init__. They are called special methods, or dunder methods, short for double underscore.

Python creates the empty object first and then calls __init__ to fill it in, which is why __init__ receives the object as self and must return None.

What is self in Python?

self is the object a method was called on. When you write ada.greet(), Python passes ada to the method as its first argument, and the method reaches the object's attributes through it.

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

    def greet(self):
        print("Hi, I'm", self.name)

ada = Player("Ada")
ada.greet()
Player.greet(ada)
Output
Hi, I'm Ada
Hi, I'm Ada

ada.greet() and Player.greet(ada) print the same line, because the dot in ada.greet() passes ada as self, and Player.greet(ada) passes it by hand. Inside greet(), self.name is the name of whichever object the method was called on.

self isn't a keyword. Python accepts any name in that first position, but every Python programmer expects self, so keep it.

How do I add methods to a Python class?

Define a function inside the class body with self as its first parameter. A function defined this way is called a method, and you call it with a dot after an object.

Python
class Player:
    def __init__(self, name):
        self.name = name
        self.score = 0

    def add_points(self, points):
        self.score += points

ada = Player("Ada")
grace = Player("Grace")
ada.add_points(10)
ada.add_points(5)
grace.add_points(7)
print(ada.name, ada.score)
print(grace.name, grace.score)
Output
Ada 15
Grace 7

Each call changes the score of the object it was called on and leaves the other object alone. Apart from self, a method works like any function from the functions and function arguments lessons, with parameters, defaults and a return value.

list is a class too, so list methods such as append() also receive the list before the dot as self.

What is the difference between class and instance attributes in Python?

An instance attribute belongs to one object, and a class attribute is shared by all of them. You create an instance attribute by assigning to an attribute of self, usually in __init__, and a class attribute by assigning a name in the class body.

Python
class Player:
    max_level = 10

    def __init__(self, name):
        self.name = name

ada = Player("Ada")
grace = Player("Grace")
print(ada.max_level, grace.max_level)

Player.max_level = 20
print(ada.max_level, grace.max_level)

ada.max_level = 99
print(ada.max_level, grace.max_level, Player.max_level)
Output
10 10
20 20
99 20 20

Changing Player.max_level changes what every player sees, because they all read it from the class. ada.max_level = 99 leaves the class alone. It creates a new instance attribute on ada that hides the class attribute, so only ada sees 99.

Class attributes and instance attributes in Python
KindCreatedShared byUse it for
Class attributeIn the class body, as in max_level = 10Every object of the classValues that are the same for every object, such as limits and defaults
Instance attributeOn self, usually in __init__, as in self.name = nameOne objectData that differs between objects, such as a name or a score

Add a __str__ method that returns a string, and print() uses it. Without one, print() falls back to __repr__, a method that describes the object for developers.

Python
class Player:
    def __init__(self, name, score):
        self.name = name
        self.score = score

    def __str__(self):
        return f"{self.name} ({self.score} points)"

ada = Player("Ada", 15)
print(ada)
print(f"Winner: {ada}")
Output
Ada (15 points)
Winner: Ada (15 points)

print() and f-strings both call __str__ to turn the object into text. It has to return a string, so build one with an f-string instead of printing inside the method.

If its class defines neither __str__ nor __repr__, an object prints as <__main__.Player object at 0x...>. The part after 0x is where the object sits in memory, written in hexadecimal, or base 16, and it usually changes from one run to the next.

Common mistakes with classes in Python

Each of these four mistakes with Python classes comes from self, __init__ or a class attribute.

  • TypeError: Player.greet() takes 0 positional arguments but 1 was given. The method was written as def greet():, without self, but Python passes the object anyway. Add self as the first parameter.
  • NameError: name 'name' is not defined. Did you mean: 'self.name'? Inside a method, print(name) looks for a variable called name, not the attribute. Write self.name.
  • TypeError: Player() takes no arguments. Python never runs a method named _init_ or __int__ when it creates an object, so nothing accepts the "Ada" in Player("Ada"). Use two underscores on each side of init.
  • A list as a class attribute. items = [] in the class body gives every object the same list, so an item appended through one object shows up in all of them. Create the list in __init__ instead, as with the shared default list in the function arguments lesson.

The program below leaves self out of greet(). Add self between the parentheses and run it again.

Python
class Player:
    def greet():
        print("Hi!")

ada = Player()
ada.greet()
Output
Traceback (most recent call last):
  File "main.py", line 6, in <module>
    ada.greet()
    ~~~~~~~~~^^
TypeError: Player.greet() takes 0 positional arguments but 1 was given

Exercise

Fix area() so it takes self and returns self.width * self.height, and the program prints 12 and then 10. The starter stops with a TypeError, because area() has no self parameter.

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

    def area():
        return width * height

box = Rectangle(3, 4)
print(box.area())
print(Rectangle(5, 2).area())
Output
Show the solution
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

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

box = Rectangle(3, 4)
print(box.area())
print(Rectangle(5, 2).area())

Quiz

This quiz has 5 questions. Pick an answer to see why it is right or wrong.

  1. 1What does this program print?

    class Counter:
        total = 0
    
    a = Counter()
    b = Counter()
    a.total = 5
    print(Counter.total, a.total, b.total)
  2. 2When ada.add_points(10) runs, what is self inside add_points()?

  3. 3What does this program print?

    class Lamp:
        def __init__(self, color="white"):
            self.color = color
    
    a = Lamp()
    b = Lamp("red")
    print(a.color, b.color)
  4. 4What does this program print?

    class Point:
        def __init__(self, x, y):
            self.x = x
            self.y = y
    
    print(Point(1, 2) == Point(1, 2))
  5. 5Which line creates an object from a class named Player?

Frequently asked questions

What is the difference between a class and an object in Python?
A class defines a type, and an object is one value made from it, also called an instance. One Player class can create any number of Player objects, each with its own attribute values.
Is self a keyword in Python?
No. self is the usual name for the first parameter of a method, which receives the object the method was called on, and any other name would work. Python programmers use self everywhere, so another name makes code harder to read.
Is __init__ a constructor in Python?
__init__ is usually called the constructor, but strictly it is an initializer. Python creates the object with __new__ first, then calls __init__ to set its attributes, and __init__ must return None.
Does every Python class need an __init__ method?
No. A class without __init__ still works, and if it lists no parent class, its objects start with no attributes of their own. Add __init__ when every object needs data from the moment it is created.
What is the difference between __str__ and __repr__ in Python?
__str__ returns the readable text that print() and f-strings show. __repr__ returns a description for developers, which repr() gives back and print() uses for objects inside a list. If a class defines only __repr__, print() shows that text too.
Why aren't two objects of my class with the same attributes equal in Python?
By default, == on objects of your own class checks whether both sides are the same object. To compare the data instead, define an __eq__ method that compares the attributes. Once a class defines __eq__ without __hash__, its objects can no longer go into a set or serve as dictionary keys.
What is a dataclass in Python?
A dataclass is a class marked with @dataclass from the dataclasses module, written on the line above the class. Python then writes its __init__, __repr__ and __eq__ methods from the names in the class body that have type hints, without checking values against those hints.