Python Arena
Step 3 of 4

Attributes of every kind

A constructor doesn't have to take every attribute as an argument. Some attributes have the same starting value in every new object: a new player has no points yet and no badges. The constructor sets those itself:

class Player:
    def __init__(self, name):
        self.name = name
        self.points = 0
        self.badges = []


ada = Player("Ada")
ben = Player("Ben")

ada.points += 15
ada.badges.append("first win")
ben.points += 5

print(ada.name, ada.points, ada.badges)
print(ben.name, ben.points, ben.badges)
Output
Ada 15 ['first win']
Ben 5 []

A few things to notice here:

  • You can change an attribute at any time, from outside the class too, like any variable: ada.points += 15.
  • An attribute can hold any kind of value: a number, a string, a list, a dictionary, a date.
  • Every object gets a list of its own. Each time the constructor runs, [] makes a new empty list, so appending to Ada's badges doesn't touch Ben's.

A date as an attribute

An attribute can hold an object such as a date, and then you can use that object's own attributes and methods through it. Read loan.borrowed.month from left to right: the loan's borrowed date, and that date's month.

from datetime import date


class Loan:
    def __init__(self, title, borrowed):
        self.title = title
        self.borrowed = borrowed
        self.returned = False


loan = Loan("Dune", date(2026, 9, 28))
print(loan.title, loan.borrowed, loan.returned)
print(loan.borrowed.month)

loan.returned = True
print(loan.returned)
Output
Dune 2026-09-28 False
9
True

Values worked out in the constructor

The constructor can also calculate an attribute from its arguments, and a parameter can have a default value, as in any function:

class Room:
    def __init__(self, name, width, length, floor=1):
        self.name = name
        self.width = width
        self.length = length
        self.area = width * length
        self.floor = floor


kitchen = Room("kitchen", 3, 4)
attic = Room("attic", 5, 6, 3)

print(kitchen.name, kitchen.area, kitchen.floor)
print(attic.name, attic.area, attic.floor)
Output
kitchen 12 1
attic 30 3

Be careful with calculated attributes: the area is worked out once, when the object is made. If the program later changes kitchen.width, kitchen.area keeps its old value. The next module shows a better way for values like this.

Your task

Challenge 1 of 3

What does this program print? Type each line it prints.

Challenge 2

Write a class Recipe whose constructor takes the recipe's name and the number of servings, and stores them in the attributes name and servings. When the servings aren't given, they are 2. Every new recipe also has the attribute ingredients, which starts as an empty list.

This code:

soup = Recipe("Tomato soup", 4)
toast = Recipe("Cheese toast")
soup.ingredients.append("tomatoes")
soup.ingredients.append("onion")
print(soup.name, soup.servings, soup.ingredients)
print(toast.name, toast.servings, toast.ingredients)

prints

Tomato soup 4 ['tomatoes', 'onion']
Cheese toast 2 []

Challenge 3

Write a class Trip whose constructor takes the destination and the first and last day of the trip as date objects. It stores them in the attributes destination, start and end, and also sets these two:

  • nights: how many nights the trip has, which is the number of days between the start and the end.
  • packed: False for every new trip.

(In part 7 you subtracted dates: the result has the attribute days.) This code:

trip = Trip("Lisbon", date(2026, 6, 1), date(2026, 6, 8))
print(trip.destination, trip.nights, trip.packed)
trip.packed = True
print(trip.start, trip.end, trip.packed)

prints

Lisbon 7 False
2026-06-01 2026-06-08 True