Classes and Objects in Python
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, andPlayer("Ada")creates an object from it.- Python runs
__init__each time you call the class to create an object, with the new object asself. ada.greet()runs the same code asPlayer.greet(ada), so the method receivesadaas its first argument.- An attribute set on
selfbelongs 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.
class Player:
def __init__(self, name):
self.name = name
ada = Player("Ada")
print(ada.name)
print(type(ada))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.
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))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").
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)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.
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)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.
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)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.
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)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.
| Kind | Created | Shared by | Use it for |
|---|---|---|---|
| Class attribute | In the class body, as in max_level = 10 | Every object of the class | Values that are the same for every object, such as limits and defaults |
| Instance attribute | On self, usually in __init__, as in self.name = name | One object | Data that differs between objects, such as a name or a score |
How do I print an object in Python?
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.
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}")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():, withoutself, but Python passes the object anyway. Addselfas the first parameter. - NameError: name 'name' is not defined. Did you mean: 'self.name'? Inside a method,
print(name)looks for a variable calledname, not the attribute. Writeself.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"inPlayer("Ada"). Use two underscores on each side ofinit. - 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.
class Player:
def greet():
print("Hi!")
ada = Player()
ada.greet()Traceback (most recent call last):
File "main.py", line 6, in <module>
ada.greet()
~~~~~~~~~^^
TypeError: Player.greet() takes 0 positional arguments but 1 was givenExercise
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.
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())
12 10
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.
-
1What does this program print?
class Counter: total = 0 a = Counter() b = Counter() a.total = 5 print(Counter.total, a.total, b.total)The line a.total = 5 gives the first object its own total and leaves Counter.total at 0. The second object has no total of its own, so it still reads the class attribute, 0.
-
2When ada.add_points(10) runs, what is self inside add_points()?
Python passes the object before the dot as the first argument, so self is ada, and 10 goes to the next parameter, points. self is the object itself, not its class, and the name self is a convention rather than a keyword.
-
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)__init__ runs once for each object. Lamp() leaves color out and gets the default white, and Lamp("red") passes red. Each object keeps its own color, so creating the second lamp doesn't change the first.
-
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))Without an __eq__ method, == checks whether both sides are the same object, and these are two separate objects. Equal attributes alone don't make them equal.
-
5Which line creates an object from a class named Player?
Calling the class with parentheses creates an object and runs __init__. Without parentheses, p = Player only gives the class a second name, and Python has no keyword called new.























