Workshop: Classes and OOP Basics (Optional, Self-Study)¶
View workshop code on GitHub Get the Video Course
From the lesson
Workshop problems for Section 13 Concepts. Build each yourself first, then expand the solution to check.
Six optional workshop problems, one per concept step, in a car scenario. Self-study: check python-workshop/solutions.
Step-01: Why Objects? Your First Class¶
Concepts: a class as a blueprint, a class attribute, creating objects.
Write a program with one class Car:
- Task-1: write the class with a class attribute
wheelsset to4. - Task-2: create two cars
c1andc2, and print each one'swheels. - Task-3: print
c1itself, to see a plain object.
The number after 0x is a memory address, so it is different on every run. Yours will not match this one.
Need a hint?
Put wheels = 4 in the class body (shared by all cars); create c1/c2 with Car() and read c1.wheels. Printing c1 itself shows the default <...Car object at 0x...> because there is no __str__ yet.
Show the solution
# Task-1: the class, with one value shared by every Car
class Car:
wheels = 4
# Task-2: create two cars and print the shared wheels
c1 = Car()
c2 = Car()
print(c1.wheels)
print(c2.wheels)
# Task-3: print the object itself, which shows a memory address, not data
print(c1)
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Step-02: Give Each Object Its Own Data (__init__ and self)¶
Concepts: __init__, self, instance attributes.
Write a program with one class Car:
- Task-1: write the class with an
__init__that takes abrandand ayear. - Task-2: create
c1(Mazda,2020) and print its brand and year on one line. - Task-3: create
c2(Tesla,2023) and print its own brand and year on one line.
Need a hint?
Store both values inside __init__ with self.brand = brand and self.year = year; each Car keeps its OWN attributes, so c2 (Tesla / 2023) stays independent of c1 (Mazda / 2020).
Show the solution
# Task-1: the class, with __init__ storing each value on self
class Car:
def __init__(self, brand, year):
self.brand = brand
self.year = year
# Task-2: create c1 and print its data
c1 = Car("Mazda", 2020)
print(c1.brand, c1.year)
# Task-3: create c2, which keeps its own data
c2 = Car("Tesla", 2023)
print(c2.brand, c2.year)
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Step-03: Class Attributes vs Instance Attributes¶
Concepts: class attribute shared by all, instance attributes per object.
Write a program with one class Car:
- Task-1: write the class with a class attribute
wheelsset to4and an__init__takingbrandandyear. - Task-2: create
c1(Mazda,2020) andc2(Tesla,2023), printc1.wheels, then printCar.wheelsstraight from the class. - Task-3: change
c1.yearto2021, then print both cars' years.
Need a hint?
wheels = 4 at class level is shared, so c1.wheels and Car.wheels are both 4; brand / year set in __init__ are per-object, so changing c1.year = 2021 leaves c2 untouched.
Show the solution
# Task-1: the class, with a shared class attribute and per-object data
class Car:
wheels = 4
def __init__(self, brand, year):
self.brand = brand
self.year = year
# Task-2: both cars, then the class attribute read from the object and from the class
c1 = Car("Mazda", 2020)
c2 = Car("Tesla", 2023)
print(c1.wheels)
print(Car.wheels)
# Task-3: an instance attribute changes for c1 only
c1.year = 2021
print(c1.year)
print(c2.year)
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Step-04: Adding Behavior with Methods¶
Concepts: a method uses self, returning vs printing.
Write a program with one class Car:
- Task-1: write the class with an
__init__that takes abrandand aspeed, a methodacceleratethat adds anamountto the speed, and a methodstatusthat RETURNS<brand> at <speed> km/h. - Task-2: create
c1(Mazda,40), accelerate it by20, and printc1.status().
Need a hint?
accelerate uses self to change state (self.speed = self.speed + amount, it ACTS), while status RETURNS f"{self.brand} at {self.speed} km/h". After c1.accelerate(20) the speed becomes 60, so c1.status() returns the line Mazda at 60 km/h.
Show the solution
# Task-1: the class, with accelerate() that ACTS and status() that RETURNS
class Car:
def __init__(self, brand, speed):
self.brand = brand
self.speed = speed
def accelerate(self, amount):
self.speed += amount
def status(self):
return f"{self.brand} at {self.speed} km/h"
# Task-2: create the car, accelerate it, then print what status() RETURNS
c1 = Car("Mazda", 40)
c1.accelerate(20)
print(c1.status())
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Step-05: Readable Objects: __str__ and __repr__¶
Concepts: __str__ friendly, __repr__ exact.
Write a program with one class Car:
- Task-1: write the class with an
__init__that takes abrandand ayear,__str__returning<brand> (<year>), and__repr__returningCar(brand='<brand>', year=<year>). - Task-2: create
c1(Mazda,2020) andc2(Tesla,2023), and printc1. - Task-3: print a list holding both cars.
Need a hint?
__str__ returns the friendly f"{self.brand} ({self.year})" that print(c1) shows; __repr__ returns the exact Car(brand='...', year=...) form (an f-string) that a list [c1, c2] shows. Match the dunder names exactly.
Show the solution
# Task-1: the class, with both dunder methods
class Car:
def __init__(self, brand, year):
self.brand = brand
self.year = year
def __str__(self):
return f"{self.brand} ({self.year})"
def __repr__(self):
return f"Car(brand={self.brand!r}, year={self.year!r})"
# Task-2: create both cars; print() uses __str__
c1 = Car("Mazda", 2020)
c2 = Car("Tesla", 2023)
print(c1)
# Task-3: a list of objects uses __repr__
print([c1, c2])
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Step-06: Class Methods and Static Methods (@classmethod and @staticmethod)¶
Concepts: the decorators @classmethod (an alternate constructor: it receives the class as cls) and @staticmethod (a related helper: it takes neither self nor cls), and asking the helper about an object the class method just built.
Write a program with one class Car:
- Task-1: write the class with an
__init__that takes abrandand ayear, a@classmethodfrom_dict(cls, data)that builds aCarfrom a dict with keysbrandandyear, and a@staticmethodis_vintage(year)that returnsTruewhenyearis below1990. - Task-2: print
Car.is_vintage(1985). - Task-3: build a car from
{"brand": "Mazda", "year": 2020}usingfrom_dict, and print its brand and year. - Task-4: print whether that car is vintage, by passing its year to
is_vintage.
Need a hint?
@staticmethod is_vintage(year) takes no self / cls, so it can simply return year < 1990. @classmethod from_dict(cls, data) receives the class as cls, so return cls(data["brand"], data["year"]) builds a Car; read it with .brand and .year, then pass that same .year back to Car.is_vintage(...) for the last line.
Show the solution
# Task-1: the class, with the two decorated methods
class Car:
def __init__(self, brand, year):
self.brand = brand
self.year = year
@classmethod
def from_dict(cls, data):
return cls(data["brand"], data["year"])
@staticmethod
def is_vintage(year):
return year < 1990
# Task-2: a static helper, no object needed
print(Car.is_vintage(1985))
# Task-3: an alternate constructor that builds a Car from a dict
c = Car.from_dict({"brand": "Mazda", "year": 2020})
print(c.brand, c.year)
# Task-4: the same static helper, now asked about the car we just built
print(Car.is_vintage(c.year))
Pages for this step: Concept | Practice | Workshop
Python Files for this step: Concept | Practice | Practice Solutions | Workshop | Workshop Solutions
Finished this section?
Check your work against the solutions above, then head back to the Section 13 lesson, or try the Section 13 practice for more reps.
Prefer to learn by watching?
The full video course teaches every concept on screen and builds the projects with you, step by step.
Workshop: Standard Library Essentials