Object-Oriented Basics
Classes
Blueprints for Objects
You're tracking users in your app. Each user has a name, email, and login method. Instead of managing separate dictionaries, a class bundles the data and behavior into one reusable blueprint - cleaner and more maintainable.
Basic class definition
Create a class with attributes and methods.
# Basic Class Definition
print("=== Basic Class ===\n")
# Define a simple class
class Dog:
pass # Empty class for now
# Create an object (instance)
my_dog = Dog()
print(f"Created: {my_dog}")
print(f"Type: {type(my_dog)}")
print("\n=== Class with Attribute ===")
class Cat:
species = "Felis catus" # Class attribute
# Create cats
cat1 = Cat()
cat2 = Cat()
print(f"Cat 1 species: {cat1.species}")
print(f"Cat 2 species: {cat2.species}")
# Both share the same class attribute
print(f"Same attribute? {cat1.species is cat2.species}")
print("\n=== Adding Instance Attributes ===")
# Add attributes to specific instance
cat1.name = "Whiskers"
cat2.name = "Luna"
print(f"Cat 1 name: {cat1.name}")
print(f"Cat 2 name: {cat2.name}")
print("\n=== Class vs Object ===")
print("""
Class = Blueprint/Template
- Defines structure
- Like a cookie cutter
Object = Instance/Reality
- Actual data
- Like actual cookies
""")
# Multiple objects from same class
dog1 = Dog()
dog2 = Dog()
dog3 = Dog()
print(f"dog1 is dog2? {dog1 is dog2}") # False - different objects
print(f"All are Dogs? {type(dog1) == type(dog2) == Dog}") # True
my_dog ← ⟨Dog A⟩, species ← (empty), cat1 ← ⟨Cat B⟩, cat2 ← ⟨Cat C⟩
3print("=== Basic Class ===\n")45# Define a simple class #?defclass6class Dog: #?classdef7 pass # Empty class for now #?pass89# Create an object (instance) #?createobj10my_dog→ ⟨Dog A⟩ = Dog() #?instantiate11print(f"Created: {my_dog⟨Dog A⟩}")12print(f"Type: {type(my_dog⟨Dog A⟩)}")1314print("\n=== Class with Attribute ===")1516class Cat: #?catwithattr17 species→ (empty) = "Felis catus" # Class attribute #?classattr1819# Create cats20cat1→ ⟨Cat B⟩ = Cat()21cat2→ ⟨Cat C⟩ = Cat()2223print(f"Cat 1 species: {cat1.speciesFelis catus}")24print(f"Cat 2 species: {cat2.speciesFelis catus}")2526# Both share the same class attribute #?shared27print(f"Same attribute? {cat1.speciesFelis catus is cat2.speciesFelis catus}")2829print("\n=== Adding Instance Attributes ===")3031# Add attributes to specific instance #?instanceattr32cat1.name→ Whiskers = "Whiskers" #?addattr33cat2.name→ Luna = "Luna"3435print(f"Cat 1 name: {cat1.nameWhiskers}")36print(f"Cat 2 name: {cat2.nameLuna}")3738print("\n=== Class vs Object ===")3940print("""41Class = Blueprint/Template42 - Defines structure43 - Like a cookie cutter4445Object = Instance/Reality46 - Actual data47 - Like actual cookies48""")4950# Multiple objects from same class #?multiple51dog1→ ⟨Dog D⟩ = Dog()52dog2→ ⟨Dog E⟩ = Dog()53dog3→ ⟨Dog F⟩ = Dog()5455print(f"dog1 is dog2? {dog1⟨Dog D⟩ is dog2⟨Dog E⟩}") # False - different objects #?different56print(f"All are Dogs? {type(dog1⟨Dog D⟩) == type(dog2⟨Dog E⟩) == Dog<class '__main__.Dog'>}") # True57#@help defclassoutput=== Basic Class === Created: ⟨Dog A⟩ Type: <class '__main__.Dog'> === Class with Attribute === Cat 1 species: Felis catus Cat 2 species: Felis catus Same attribute? True === Adding Instance Attributes === Cat 1 name: Whiskers Cat 2 name: Luna === Class vs Object === Class = Blueprint/Template - Defines structure - Like a cookie cutter Object = Instance/Reality - Actual data - Like actual cookies dog1 is dog2? False All are Dogs? True
class Name: defines a blueprint. Methods are functions inside the class.
Instance attributes
Each object has its own copy of attributes.
# Instance Attributes with __init__
print("=== The __init__ Method ===\n")
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
print(f"Creating dog: {name}, age {age}")
# Create dogs
buddy = Dog("Buddy", 3)
max_dog = Dog("Max", 5)
print(f"\n{buddy.name} is {buddy.age} years old")
print(f"{max_dog.name} is {max_dog.age} years old")
print("\n=== Default Values ===")
class Cat:
def __init__(self, name, color="orange"):
self.name = name
self.color = color
# With and without default
garfield = Cat("Garfield") # Uses default color
whiskers = Cat("Whiskers", "gray")
print(f"{garfield.name} is {garfield.color}")
print(f"{whiskers.name} is {whiskers.color}")
print("\n=== Multiple Initialization Patterns ===")
class Person:
def __init__(self, name, age=0, city="Unknown"):
self.name = name
self.age = age
self.city = city
def display(self):
print(f"{self.name}, {self.age}, from {self.city}")
# Various ways to create
p1 = Person("Alice")
p2 = Person("Bob", 25)
p3 = Person("Carol", 30, "NYC")
p4 = Person("Dave", city="LA")
p1.display()
p2.display()
p3.display()
p4.display()
print("\n=== Computed Attributes ===")
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
self.area = width * height
self.perimeter = 2 * (width + height)
rect = Rectangle(5, 3)
print(f"Rectangle {rect.width}x{rect.height}")
print(f"Area: {rect.area}")
print(f"Perimeter: {rect.perimeter}")
# Instance Attributes with __init__
print("=== The __init__ Method ===\n")
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
print(f"Creating dog: {name}, age {age}")
# Create dogs
buddy = Dog("Rex", 2)
max_dog = Dog("Max", 5)
print(f"\n{buddy.name} is {buddy.age} years old")
print(f"{max_dog.name} is {max_dog.age} years old")
print("\n=== Default Values ===")
class Cat:
def __init__(self, name, color="orange"):
self.name = name
self.color = color
# With and without default
garfield = Cat("Garfield") # Uses default color
whiskers = Cat("Whiskers", "gray")
print(f"{garfield.name} is {garfield.color}")
print(f"{whiskers.name} is {whiskers.color}")
print("\n=== Multiple Initialization Patterns ===")
class Person:
def __init__(self, name, age=0, city="Unknown"):
self.name = name
self.age = age
self.city = city
def display(self):
print(f"{self.name}, {self.age}, from {self.city}")
# Various ways to create
p1 = Person("Alice")
p2 = Person("Bob", 25)
p3 = Person("Carol", 30, "NYC")
p4 = Person("Dave", city="LA")
p1.display()
p2.display()
p3.display()
p4.display()
print("\n=== Computed Attributes ===")
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
self.area = width * height
self.perimeter = 2 * (width + height)
rect = Rectangle(5, 3)
print(f"Rectangle {rect.width}x{rect.height}")
print(f"Area: {rect.area}")
print(f"Perimeter: {rect.perimeter}")
# Instance Attributes with __init__
print("=== The __init__ Method ===\n")
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
print(f"Creating dog: {name}, age {age}")
# Create dogs
buddy = Dog("Luna", 7)
max_dog = Dog("Max", 5)
print(f"\n{buddy.name} is {buddy.age} years old")
print(f"{max_dog.name} is {max_dog.age} years old")
print("\n=== Default Values ===")
class Cat:
def __init__(self, name, color="orange"):
self.name = name
self.color = color
# With and without default
garfield = Cat("Garfield") # Uses default color
whiskers = Cat("Whiskers", "gray")
print(f"{garfield.name} is {garfield.color}")
print(f"{whiskers.name} is {whiskers.color}")
print("\n=== Multiple Initialization Patterns ===")
class Person:
def __init__(self, name, age=0, city="Unknown"):
self.name = name
self.age = age
self.city = city
def display(self):
print(f"{self.name}, {self.age}, from {self.city}")
# Various ways to create
p1 = Person("Alice")
p2 = Person("Bob", 25)
p3 = Person("Carol", 30, "NYC")
p4 = Person("Dave", city="LA")
p1.display()
p2.display()
p3.display()
p4.display()
print("\n=== Computed Attributes ===")
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
self.area = width * height
self.perimeter = 2 * (width + height)
rect = Rectangle(5, 3)
print(f"Rectangle {rect.width}x{rect.height}")
print(f"Area: {rect.area}")
print(f"Perimeter: {rect.perimeter}")
# Instance Attributes with __init__
print("=== The __init__ Method ===\n")
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
print(f"Creating dog: {name}, age {age}")
# Create dogs
buddy = Dog("Buddy", 3)
max_dog = Dog("Max", 5)
print(f"\n{buddy.name} is {buddy.age} years old")
print(f"{max_dog.name} is {max_dog.age} years old")
print("\n=== Default Values ===")
class Cat:
def __init__(self, name, color="orange"):
self.name = name
self.color = color
# With and without default
garfield = Cat("Garfield") # Uses default color
whiskers = Cat("Whiskers", "gray")
print(f"{garfield.name} is {garfield.color}")
print(f"{whiskers.name} is {whiskers.color}")
print("\n=== Multiple Initialization Patterns ===")
class Person:
def __init__(self, name, age=0, city="Unknown"):
self.name = name
self.age = age
self.city = city
def display(self):
print(f"{self.name}, {self.age}, from {self.city}")
# Various ways to create
p1 = Person("Alice")
p2 = Person("Bob", 25)
p3 = Person("Carol", 30, "NYC")
p4 = Person("Dave", city="LA")
p1.display()
p2.display()
p3.display()
p4.display()
print("\n=== Computed Attributes ===")
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
self.area = width * height
self.perimeter = 2 * (width + height)
rect = Rectangle(4, 4)
print(f"Rectangle {rect.width}x{rect.height}")
print(f"Area: {rect.area}")
print(f"Perimeter: {rect.perimeter}")
# Instance Attributes with __init__
print("=== The __init__ Method ===\n")
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
print(f"Creating dog: {name}, age {age}")
# Create dogs
buddy = Dog("Buddy", 3)
max_dog = Dog("Max", 5)
print(f"\n{buddy.name} is {buddy.age} years old")
print(f"{max_dog.name} is {max_dog.age} years old")
print("\n=== Default Values ===")
class Cat:
def __init__(self, name, color="orange"):
self.name = name
self.color = color
# With and without default
garfield = Cat("Garfield") # Uses default color
whiskers = Cat("Whiskers", "gray")
print(f"{garfield.name} is {garfield.color}")
print(f"{whiskers.name} is {whiskers.color}")
print("\n=== Multiple Initialization Patterns ===")
class Person:
def __init__(self, name, age=0, city="Unknown"):
self.name = name
self.age = age
self.city = city
def display(self):
print(f"{self.name}, {self.age}, from {self.city}")
# Various ways to create
p1 = Person("Alice")
p2 = Person("Bob", 25)
p3 = Person("Carol", 30, "NYC")
p4 = Person("Dave", city="LA")
p1.display()
p2.display()
p3.display()
p4.display()
print("\n=== Computed Attributes ===")
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
self.area = width * height
self.perimeter = 2 * (width + height)
rect = Rectangle(8, 2)
print(f"Rectangle {rect.width}x{rect.height}")
print(f"Area: {rect.area}")
print(f"Perimeter: {rect.perimeter}")
print("=== The __init__ Method === ")
3print("=== The __init__ Method ===\n")45class Dog:6 def __init__(self, name, age): #?init7 self.name = name #?selfattr8 self.age = age9 print(f"Creating dog: {name}, age {age}")1011# Create dogs #?createwithargs12buddy = Dog("Buddy", 3) #?passargs13#@buddy=Dog("Rex", 2), Dog("Luna", 7)output=== The __init__ Method ===self.name ← Buddy, self.age ← 3
pass 1 of 25class Dog:6 def __init__(self⟨Dog A⟩, nameBuddy, age3): #?init7 self.name→ Buddy = nameBuddy #?selfattr8 self.age→ 3 = age39 print(f"Creating dog: {nameBuddy}, age {age3}")outputCreating dog: Buddy, age 3buddy ← ⟨Dog A⟩
11# Create dogs #?createwithargs12buddy→ ⟨Dog A⟩ = Dog("Buddy", 3) #?passargs13#@buddy=Dog("Rex", 2), Dog("Luna", 7)14max_dog = Dog("Max", 5)self.name ← Max, self.age ← 5
pass 2 of 25class Dog:6 def __init__(self⟨Dog B⟩, nameMax, age5): #?init7 self.name→ Max = nameMax #?selfattr8 self.age→ 5 = age59 print(f"Creating dog: {nameMax}, age {age5}")outputCreating dog: Max, age 5max_dog ← ⟨Dog B⟩
13#@buddy=Dog("Rex", 2), Dog("Luna", 7)14max_dog→ ⟨Dog B⟩ = Dog("Max", 5)1516print(f"\n{buddy.nameBuddy} is {buddy.age3} years old")17print(f"{max_dog.nameMax} is {max_dog.age5} years old")1819print("\n=== Default Values ===")2021class Cat:22 def __init__(self, name, color="orange"): #?default23 self.name = name24 self.color = color2526# With and without default #?usedefault27garfield = Cat("Garfield") # Uses default color28whiskers = Cat("Whiskers", "gray")output Buddy is 3 years old Max is 5 years old === Default Values ===self.name ← Garfield, self.color ← orange
pass 1 of 221class Cat:22 def __init__(self⟨Cat C⟩, nameGarfield, colororange="orange"): #?default23 self.name→ Garfield = nameGarfield24 self.color→ orange = colororangegarfield ← ⟨Cat C⟩
26# With and without default #?usedefault27garfield→ ⟨Cat C⟩ = Cat("Garfield") # Uses default color28whiskers = Cat("Whiskers", "gray")self.name ← Whiskers, self.color ← gray
pass 2 of 221class Cat:22 def __init__(self⟨Cat D⟩, nameWhiskers, colorgray="orange"): #?default23 self.name→ Whiskers = nameWhiskers24 self.color→ gray = colorgraywhiskers ← ⟨Cat D⟩
27garfield = Cat("Garfield") # Uses default color28whiskers→ ⟨Cat D⟩ = Cat("Whiskers", "gray")2930print(f"{garfield.nameGarfield} is {garfield.colororange}")31print(f"{whiskers.nameWhiskers} is {whiskers.colorgray}")3233print("\n=== Multiple Initialization Patterns ===")3435class Person:36 def __init__(self, name, age=0, city="Unknown"): #?multidefault37 self.name = name38 self.age = age39 self.city = city40 41 def display(self):42 print(f"{self.name}, {self.age}, from {self.city}")4344# Various ways to create #?createvarious45p1 = Person("Alice")46p2 = Person("Bob", 25)outputGarfield is orange Whiskers is gray === Multiple Initialization Patterns ===self.name ← Alice, self.age ← 0, self.city ← Unknown
pass 1 of 435class Person:36 def __init__(self⟨Person E⟩, nameAlice, age0=0, cityUnknown="Unknown"): #?multidefault37 self.name→ Alice = nameAlice38 self.age→ 0 = age039 self.city→ Unknown = cityUnknownAll 4 passes — pass 1 is the card above pass selfnameagecityself.nameself.ageself.city1 ⟨Person E⟩ Alice 0 Unknown Alice 0 Unknown 2 ⟨Person F⟩ Bob 25 Unknown Bob 25 Unknown 3 ⟨Person G⟩ Carol 30 NYC Carol 30 NYC 4 ⟨Person H⟩ Dave 0 LA Dave 0 LA p1 ← ⟨Person E⟩
44# Various ways to create #?createvarious45p1→ ⟨Person E⟩ = Person("Alice")46p2 = Person("Bob", 25)47p3 = Person("Carol", 30, "NYC")p2 ← ⟨Person F⟩
45p1 = Person("Alice")46p2→ ⟨Person F⟩ = Person("Bob", 25)47p3 = Person("Carol", 30, "NYC")48p4 = Person("Dave", city="LA") #?namedargp3 ← ⟨Person G⟩
46p2 = Person("Bob", 25)47p3→ ⟨Person G⟩ = Person("Carol", 30, "NYC")48p4 = Person("Dave", city="LA") #?namedargp4 ← ⟨Person H⟩
47p3 = Person("Carol", 30, "NYC")48p4→ ⟨Person H⟩ = Person("Dave", city="LA") #?namedarg4950p1⟨Person E⟩.display()51p2.display()def display(self):
pass 1 of 441def display(self⟨Person E⟩):42 print(f"{self.nameAlice}, {self.age0}, from {self.cityUnknown}")outputAlice, 0, from UnknownAll 4 passes — pass 1 is the card above pass selfself.nameself.ageself.city1 ⟨Person E⟩ Alice 0 Unknown 2 ⟨Person F⟩ Bob 25 Unknown 3 ⟨Person G⟩ Carol 30 NYC 4 ⟨Person H⟩ Dave 0 LA p1.display()
50p1⟨Person E⟩.display()51p2⟨Person F⟩.display()52p3.display()p2.display()
50p1.display()51p2⟨Person F⟩.display()52p3⟨Person G⟩.display()53p4.display()p3.display()
51p2.display()52p3⟨Person G⟩.display()53p4⟨Person H⟩.display()p4.display()
52p3.display()53p4⟨Person H⟩.display()5455print("\n=== Computed Attributes ===")5657class Rectangle:58 def __init__(self, width, height):59 self.width = width60 self.height = height61 self.area = width * height #?computed62 self.perimeter = 2 * (width + height)6364rect = Rectangle(5, 3) #@rect=Rectangle(4, 4), Rectangle(8, 2)65print(f"Rectangle {rect.width}x{rect.height}")output === Computed Attributes ===self.width ← 5, self.height ← 3, self.area ← 15, self.perimeter ← 16
57class Rectangle:58 def __init__(self⟨Rectangle I⟩, width5, height3):59 self.width→ 5 = width560 self.height→ 3 = height361 self.area→ 15 = width5 * height3 #?computed62 self.perimeter→ 16 = 2 * (width5 + height3)rect ← ⟨Rectangle I⟩
64rect→ ⟨Rectangle I⟩ = Rectangle(5, 3) #@rect=Rectangle(4, 4), Rectangle(8, 2)65print(f"Rectangle {rect.width5}x{rect.height3}")66print(f"Area: {rect.area15}")67print(f"Perimeter: {rect.perimeter16}")68#@help initoutputRectangle 5x3 Area: 15 Perimeter: 16
print("=== The __init__ Method === ")
3print("=== The __init__ Method ===\n")45class Dog:6 def __init__(self, name, age):7 self.name = name8 self.age = age9 print(f"Creating dog: {name}, age {age}")1011# Create dogs12buddy = Dog("Rex", 2)13max_dog = Dog("Max", 5)output=== The __init__ Method ===self.name ← Rex, self.age ← 2
pass 1 of 25class Dog:6 def __init__(self⟨Dog A⟩, nameRex, age2):7 self.name→ Rex = nameRex8 self.age→ 2 = age29 print(f"Creating dog: {nameRex}, age {age2}")outputCreating dog: Rex, age 2buddy ← ⟨Dog A⟩
11# Create dogs12buddy→ ⟨Dog A⟩ = Dog("Rex", 2)13max_dog = Dog("Max", 5)self.name ← Max, self.age ← 5
pass 2 of 25class Dog:6 def __init__(self⟨Dog B⟩, nameMax, age5):7 self.name→ Max = nameMax8 self.age→ 5 = age59 print(f"Creating dog: {nameMax}, age {age5}")outputCreating dog: Max, age 5max_dog ← ⟨Dog B⟩
12buddy = Dog("Rex", 2)13max_dog→ ⟨Dog B⟩ = Dog("Max", 5)1415print(f"\n{buddy.nameRex} is {buddy.age2} years old")16print(f"{max_dog.nameMax} is {max_dog.age5} years old")1718print("\n=== Default Values ===")1920class Cat:21 def __init__(self, name, color="orange"):22 self.name = name23 self.color = color2425# With and without default26garfield = Cat("Garfield") # Uses default color27whiskers = Cat("Whiskers", "gray")output Rex is 2 years old Max is 5 years old === Default Values ===self.name ← Garfield, self.color ← orange
pass 1 of 220class Cat:21 def __init__(self⟨Cat C⟩, nameGarfield, colororange="orange"):22 self.name→ Garfield = nameGarfield23 self.color→ orange = colororangegarfield ← ⟨Cat C⟩
25# With and without default26garfield→ ⟨Cat C⟩ = Cat("Garfield") # Uses default color27whiskers = Cat("Whiskers", "gray")self.name ← Whiskers, self.color ← gray
pass 2 of 220class Cat:21 def __init__(self⟨Cat D⟩, nameWhiskers, colorgray="orange"):22 self.name→ Whiskers = nameWhiskers23 self.color→ gray = colorgraywhiskers ← ⟨Cat D⟩
26garfield = Cat("Garfield") # Uses default color27whiskers→ ⟨Cat D⟩ = Cat("Whiskers", "gray")2829print(f"{garfield.nameGarfield} is {garfield.colororange}")30print(f"{whiskers.nameWhiskers} is {whiskers.colorgray}")3132print("\n=== Multiple Initialization Patterns ===")3334class Person:35 def __init__(self, name, age=0, city="Unknown"):36 self.name = name37 self.age = age38 self.city = city39 40 def display(self):41 print(f"{self.name}, {self.age}, from {self.city}")4243# Various ways to create44p1 = Person("Alice")45p2 = Person("Bob", 25)outputGarfield is orange Whiskers is gray === Multiple Initialization Patterns ===self.name ← Alice, self.age ← 0, self.city ← Unknown
pass 1 of 434class Person:35 def __init__(self⟨Person E⟩, nameAlice, age0=0, cityUnknown="Unknown"):36 self.name→ Alice = nameAlice37 self.age→ 0 = age038 self.city→ Unknown = cityUnknownAll 4 passes — pass 1 is the card above pass selfnameagecityself.nameself.ageself.city1 ⟨Person E⟩ Alice 0 Unknown Alice 0 Unknown 2 ⟨Person F⟩ Bob 25 Unknown Bob 25 Unknown 3 ⟨Person G⟩ Carol 30 NYC Carol 30 NYC 4 ⟨Person H⟩ Dave 0 LA Dave 0 LA p1 ← ⟨Person E⟩
43# Various ways to create44p1→ ⟨Person E⟩ = Person("Alice")45p2 = Person("Bob", 25)46p3 = Person("Carol", 30, "NYC")p2 ← ⟨Person F⟩
44p1 = Person("Alice")45p2→ ⟨Person F⟩ = Person("Bob", 25)46p3 = Person("Carol", 30, "NYC")47p4 = Person("Dave", city="LA")p3 ← ⟨Person G⟩
45p2 = Person("Bob", 25)46p3→ ⟨Person G⟩ = Person("Carol", 30, "NYC")47p4 = Person("Dave", city="LA")p4 ← ⟨Person H⟩
46p3 = Person("Carol", 30, "NYC")47p4→ ⟨Person H⟩ = Person("Dave", city="LA")4849p1⟨Person E⟩.display()50p2.display()def display(self):
pass 1 of 440def display(self⟨Person E⟩):41 print(f"{self.nameAlice}, {self.age0}, from {self.cityUnknown}")outputAlice, 0, from UnknownAll 4 passes — pass 1 is the card above pass selfself.nameself.ageself.city1 ⟨Person E⟩ Alice 0 Unknown 2 ⟨Person F⟩ Bob 25 Unknown 3 ⟨Person G⟩ Carol 30 NYC 4 ⟨Person H⟩ Dave 0 LA p1.display()
49p1⟨Person E⟩.display()50p2⟨Person F⟩.display()51p3.display()p2.display()
49p1.display()50p2⟨Person F⟩.display()51p3⟨Person G⟩.display()52p4.display()p3.display()
50p2.display()51p3⟨Person G⟩.display()52p4⟨Person H⟩.display()p4.display()
51p3.display()52p4⟨Person H⟩.display()5354print("\n=== Computed Attributes ===")5556class Rectangle:57 def __init__(self, width, height):58 self.width = width59 self.height = height60 self.area = width * height61 self.perimeter = 2 * (width + height)6263rect = Rectangle(5, 3)64print(f"Rectangle {rect.width}x{rect.height}")output === Computed Attributes ===self.width ← 5, self.height ← 3, self.area ← 15, self.perimeter ← 16
56class Rectangle:57 def __init__(self⟨Rectangle I⟩, width5, height3):58 self.width→ 5 = width559 self.height→ 3 = height360 self.area→ 15 = width5 * height361 self.perimeter→ 16 = 2 * (width5 + height3)rect ← ⟨Rectangle I⟩
63rect→ ⟨Rectangle I⟩ = Rectangle(5, 3)64print(f"Rectangle {rect.width5}x{rect.height3}")65print(f"Area: {rect.area15}")66print(f"Perimeter: {rect.perimeter16}")outputRectangle 5x3 Area: 15 Perimeter: 16
print("=== The __init__ Method === ")
3print("=== The __init__ Method ===\n")45class Dog:6 def __init__(self, name, age):7 self.name = name8 self.age = age9 print(f"Creating dog: {name}, age {age}")1011# Create dogs12buddy = Dog("Luna", 7)13max_dog = Dog("Max", 5)output=== The __init__ Method ===self.name ← Luna, self.age ← 7
pass 1 of 25class Dog:6 def __init__(self⟨Dog A⟩, nameLuna, age7):7 self.name→ Luna = nameLuna8 self.age→ 7 = age79 print(f"Creating dog: {nameLuna}, age {age7}")outputCreating dog: Luna, age 7buddy ← ⟨Dog A⟩
11# Create dogs12buddy→ ⟨Dog A⟩ = Dog("Luna", 7)13max_dog = Dog("Max", 5)self.name ← Max, self.age ← 5
pass 2 of 25class Dog:6 def __init__(self⟨Dog B⟩, nameMax, age5):7 self.name→ Max = nameMax8 self.age→ 5 = age59 print(f"Creating dog: {nameMax}, age {age5}")outputCreating dog: Max, age 5max_dog ← ⟨Dog B⟩
12buddy = Dog("Luna", 7)13max_dog→ ⟨Dog B⟩ = Dog("Max", 5)1415print(f"\n{buddy.nameLuna} is {buddy.age7} years old")16print(f"{max_dog.nameMax} is {max_dog.age5} years old")1718print("\n=== Default Values ===")1920class Cat:21 def __init__(self, name, color="orange"):22 self.name = name23 self.color = color2425# With and without default26garfield = Cat("Garfield") # Uses default color27whiskers = Cat("Whiskers", "gray")output Luna is 7 years old Max is 5 years old === Default Values ===self.name ← Garfield, self.color ← orange
pass 1 of 220class Cat:21 def __init__(self⟨Cat C⟩, nameGarfield, colororange="orange"):22 self.name→ Garfield = nameGarfield23 self.color→ orange = colororangegarfield ← ⟨Cat C⟩
25# With and without default26garfield→ ⟨Cat C⟩ = Cat("Garfield") # Uses default color27whiskers = Cat("Whiskers", "gray")self.name ← Whiskers, self.color ← gray
pass 2 of 220class Cat:21 def __init__(self⟨Cat D⟩, nameWhiskers, colorgray="orange"):22 self.name→ Whiskers = nameWhiskers23 self.color→ gray = colorgraywhiskers ← ⟨Cat D⟩
26garfield = Cat("Garfield") # Uses default color27whiskers→ ⟨Cat D⟩ = Cat("Whiskers", "gray")2829print(f"{garfield.nameGarfield} is {garfield.colororange}")30print(f"{whiskers.nameWhiskers} is {whiskers.colorgray}")3132print("\n=== Multiple Initialization Patterns ===")3334class Person:35 def __init__(self, name, age=0, city="Unknown"):36 self.name = name37 self.age = age38 self.city = city39 40 def display(self):41 print(f"{self.name}, {self.age}, from {self.city}")4243# Various ways to create44p1 = Person("Alice")45p2 = Person("Bob", 25)outputGarfield is orange Whiskers is gray === Multiple Initialization Patterns ===self.name ← Alice, self.age ← 0, self.city ← Unknown
pass 1 of 434class Person:35 def __init__(self⟨Person E⟩, nameAlice, age0=0, cityUnknown="Unknown"):36 self.name→ Alice = nameAlice37 self.age→ 0 = age038 self.city→ Unknown = cityUnknownAll 4 passes — pass 1 is the card above pass selfnameagecityself.nameself.ageself.city1 ⟨Person E⟩ Alice 0 Unknown Alice 0 Unknown 2 ⟨Person F⟩ Bob 25 Unknown Bob 25 Unknown 3 ⟨Person G⟩ Carol 30 NYC Carol 30 NYC 4 ⟨Person H⟩ Dave 0 LA Dave 0 LA p1 ← ⟨Person E⟩
43# Various ways to create44p1→ ⟨Person E⟩ = Person("Alice")45p2 = Person("Bob", 25)46p3 = Person("Carol", 30, "NYC")p2 ← ⟨Person F⟩
44p1 = Person("Alice")45p2→ ⟨Person F⟩ = Person("Bob", 25)46p3 = Person("Carol", 30, "NYC")47p4 = Person("Dave", city="LA")p3 ← ⟨Person G⟩
45p2 = Person("Bob", 25)46p3→ ⟨Person G⟩ = Person("Carol", 30, "NYC")47p4 = Person("Dave", city="LA")p4 ← ⟨Person H⟩
46p3 = Person("Carol", 30, "NYC")47p4→ ⟨Person H⟩ = Person("Dave", city="LA")4849p1⟨Person E⟩.display()50p2.display()def display(self):
pass 1 of 440def display(self⟨Person E⟩):41 print(f"{self.nameAlice}, {self.age0}, from {self.cityUnknown}")outputAlice, 0, from UnknownAll 4 passes — pass 1 is the card above pass selfself.nameself.ageself.city1 ⟨Person E⟩ Alice 0 Unknown 2 ⟨Person F⟩ Bob 25 Unknown 3 ⟨Person G⟩ Carol 30 NYC 4 ⟨Person H⟩ Dave 0 LA p1.display()
49p1⟨Person E⟩.display()50p2⟨Person F⟩.display()51p3.display()p2.display()
49p1.display()50p2⟨Person F⟩.display()51p3⟨Person G⟩.display()52p4.display()p3.display()
50p2.display()51p3⟨Person G⟩.display()52p4⟨Person H⟩.display()p4.display()
51p3.display()52p4⟨Person H⟩.display()5354print("\n=== Computed Attributes ===")5556class Rectangle:57 def __init__(self, width, height):58 self.width = width59 self.height = height60 self.area = width * height61 self.perimeter = 2 * (width + height)6263rect = Rectangle(5, 3)64print(f"Rectangle {rect.width}x{rect.height}")output === Computed Attributes ===self.width ← 5, self.height ← 3, self.area ← 15, self.perimeter ← 16
56class Rectangle:57 def __init__(self⟨Rectangle I⟩, width5, height3):58 self.width→ 5 = width559 self.height→ 3 = height360 self.area→ 15 = width5 * height361 self.perimeter→ 16 = 2 * (width5 + height3)rect ← ⟨Rectangle I⟩
63rect→ ⟨Rectangle I⟩ = Rectangle(5, 3)64print(f"Rectangle {rect.width5}x{rect.height3}")65print(f"Area: {rect.area15}")66print(f"Perimeter: {rect.perimeter16}")outputRectangle 5x3 Area: 15 Perimeter: 16
print("=== The __init__ Method === ")
3print("=== The __init__ Method ===\n")45class Dog:6 def __init__(self, name, age):7 self.name = name8 self.age = age9 print(f"Creating dog: {name}, age {age}")1011# Create dogs12buddy = Dog("Buddy", 3)13max_dog = Dog("Max", 5)output=== The __init__ Method ===self.name ← Buddy, self.age ← 3
pass 1 of 25class Dog:6 def __init__(self⟨Dog A⟩, nameBuddy, age3):7 self.name→ Buddy = nameBuddy8 self.age→ 3 = age39 print(f"Creating dog: {nameBuddy}, age {age3}")outputCreating dog: Buddy, age 3buddy ← ⟨Dog A⟩
11# Create dogs12buddy→ ⟨Dog A⟩ = Dog("Buddy", 3)13max_dog = Dog("Max", 5)self.name ← Max, self.age ← 5
pass 2 of 25class Dog:6 def __init__(self⟨Dog B⟩, nameMax, age5):7 self.name→ Max = nameMax8 self.age→ 5 = age59 print(f"Creating dog: {nameMax}, age {age5}")outputCreating dog: Max, age 5max_dog ← ⟨Dog B⟩
12buddy = Dog("Buddy", 3)13max_dog→ ⟨Dog B⟩ = Dog("Max", 5)1415print(f"\n{buddy.nameBuddy} is {buddy.age3} years old")16print(f"{max_dog.nameMax} is {max_dog.age5} years old")1718print("\n=== Default Values ===")1920class Cat:21 def __init__(self, name, color="orange"):22 self.name = name23 self.color = color2425# With and without default26garfield = Cat("Garfield") # Uses default color27whiskers = Cat("Whiskers", "gray")output Buddy is 3 years old Max is 5 years old === Default Values ===self.name ← Garfield, self.color ← orange
pass 1 of 220class Cat:21 def __init__(self⟨Cat C⟩, nameGarfield, colororange="orange"):22 self.name→ Garfield = nameGarfield23 self.color→ orange = colororangegarfield ← ⟨Cat C⟩
25# With and without default26garfield→ ⟨Cat C⟩ = Cat("Garfield") # Uses default color27whiskers = Cat("Whiskers", "gray")self.name ← Whiskers, self.color ← gray
pass 2 of 220class Cat:21 def __init__(self⟨Cat D⟩, nameWhiskers, colorgray="orange"):22 self.name→ Whiskers = nameWhiskers23 self.color→ gray = colorgraywhiskers ← ⟨Cat D⟩
26garfield = Cat("Garfield") # Uses default color27whiskers→ ⟨Cat D⟩ = Cat("Whiskers", "gray")2829print(f"{garfield.nameGarfield} is {garfield.colororange}")30print(f"{whiskers.nameWhiskers} is {whiskers.colorgray}")3132print("\n=== Multiple Initialization Patterns ===")3334class Person:35 def __init__(self, name, age=0, city="Unknown"):36 self.name = name37 self.age = age38 self.city = city39 40 def display(self):41 print(f"{self.name}, {self.age}, from {self.city}")4243# Various ways to create44p1 = Person("Alice")45p2 = Person("Bob", 25)outputGarfield is orange Whiskers is gray === Multiple Initialization Patterns ===self.name ← Alice, self.age ← 0, self.city ← Unknown
pass 1 of 434class Person:35 def __init__(self⟨Person E⟩, nameAlice, age0=0, cityUnknown="Unknown"):36 self.name→ Alice = nameAlice37 self.age→ 0 = age038 self.city→ Unknown = cityUnknownAll 4 passes — pass 1 is the card above pass selfnameagecityself.nameself.ageself.city1 ⟨Person E⟩ Alice 0 Unknown Alice 0 Unknown 2 ⟨Person F⟩ Bob 25 Unknown Bob 25 Unknown 3 ⟨Person G⟩ Carol 30 NYC Carol 30 NYC 4 ⟨Person H⟩ Dave 0 LA Dave 0 LA p1 ← ⟨Person E⟩
43# Various ways to create44p1→ ⟨Person E⟩ = Person("Alice")45p2 = Person("Bob", 25)46p3 = Person("Carol", 30, "NYC")p2 ← ⟨Person F⟩
44p1 = Person("Alice")45p2→ ⟨Person F⟩ = Person("Bob", 25)46p3 = Person("Carol", 30, "NYC")47p4 = Person("Dave", city="LA")p3 ← ⟨Person G⟩
45p2 = Person("Bob", 25)46p3→ ⟨Person G⟩ = Person("Carol", 30, "NYC")47p4 = Person("Dave", city="LA")p4 ← ⟨Person H⟩
46p3 = Person("Carol", 30, "NYC")47p4→ ⟨Person H⟩ = Person("Dave", city="LA")4849p1⟨Person E⟩.display()50p2.display()def display(self):
pass 1 of 440def display(self⟨Person E⟩):41 print(f"{self.nameAlice}, {self.age0}, from {self.cityUnknown}")outputAlice, 0, from UnknownAll 4 passes — pass 1 is the card above pass selfself.nameself.ageself.city1 ⟨Person E⟩ Alice 0 Unknown 2 ⟨Person F⟩ Bob 25 Unknown 3 ⟨Person G⟩ Carol 30 NYC 4 ⟨Person H⟩ Dave 0 LA p1.display()
49p1⟨Person E⟩.display()50p2⟨Person F⟩.display()51p3.display()p2.display()
49p1.display()50p2⟨Person F⟩.display()51p3⟨Person G⟩.display()52p4.display()p3.display()
50p2.display()51p3⟨Person G⟩.display()52p4⟨Person H⟩.display()p4.display()
51p3.display()52p4⟨Person H⟩.display()5354print("\n=== Computed Attributes ===")5556class Rectangle:57 def __init__(self, width, height):58 self.width = width59 self.height = height60 self.area = width * height61 self.perimeter = 2 * (width + height)6263rect = Rectangle(4, 4)64print(f"Rectangle {rect.width}x{rect.height}")output === Computed Attributes ===self.width ← 4, self.height ← 4, self.area ← 16, self.perimeter ← 16
56class Rectangle:57 def __init__(self⟨Rectangle I⟩, width4, height4):58 self.width→ 4 = width459 self.height→ 4 = height460 self.area→ 16 = width4 * height461 self.perimeter→ 16 = 2 * (width4 + height4)rect ← ⟨Rectangle I⟩
63rect→ ⟨Rectangle I⟩ = Rectangle(4, 4)64print(f"Rectangle {rect.width4}x{rect.height4}")65print(f"Area: {rect.area16}")66print(f"Perimeter: {rect.perimeter16}")outputRectangle 4x4 Area: 16 Perimeter: 16
print("=== The __init__ Method === ")
3print("=== The __init__ Method ===\n")45class Dog:6 def __init__(self, name, age):7 self.name = name8 self.age = age9 print(f"Creating dog: {name}, age {age}")1011# Create dogs12buddy = Dog("Buddy", 3)13max_dog = Dog("Max", 5)output=== The __init__ Method ===self.name ← Buddy, self.age ← 3
pass 1 of 25class Dog:6 def __init__(self⟨Dog A⟩, nameBuddy, age3):7 self.name→ Buddy = nameBuddy8 self.age→ 3 = age39 print(f"Creating dog: {nameBuddy}, age {age3}")outputCreating dog: Buddy, age 3buddy ← ⟨Dog A⟩
11# Create dogs12buddy→ ⟨Dog A⟩ = Dog("Buddy", 3)13max_dog = Dog("Max", 5)self.name ← Max, self.age ← 5
pass 2 of 25class Dog:6 def __init__(self⟨Dog B⟩, nameMax, age5):7 self.name→ Max = nameMax8 self.age→ 5 = age59 print(f"Creating dog: {nameMax}, age {age5}")outputCreating dog: Max, age 5max_dog ← ⟨Dog B⟩
12buddy = Dog("Buddy", 3)13max_dog→ ⟨Dog B⟩ = Dog("Max", 5)1415print(f"\n{buddy.nameBuddy} is {buddy.age3} years old")16print(f"{max_dog.nameMax} is {max_dog.age5} years old")1718print("\n=== Default Values ===")1920class Cat:21 def __init__(self, name, color="orange"):22 self.name = name23 self.color = color2425# With and without default26garfield = Cat("Garfield") # Uses default color27whiskers = Cat("Whiskers", "gray")output Buddy is 3 years old Max is 5 years old === Default Values ===self.name ← Garfield, self.color ← orange
pass 1 of 220class Cat:21 def __init__(self⟨Cat C⟩, nameGarfield, colororange="orange"):22 self.name→ Garfield = nameGarfield23 self.color→ orange = colororangegarfield ← ⟨Cat C⟩
25# With and without default26garfield→ ⟨Cat C⟩ = Cat("Garfield") # Uses default color27whiskers = Cat("Whiskers", "gray")self.name ← Whiskers, self.color ← gray
pass 2 of 220class Cat:21 def __init__(self⟨Cat D⟩, nameWhiskers, colorgray="orange"):22 self.name→ Whiskers = nameWhiskers23 self.color→ gray = colorgraywhiskers ← ⟨Cat D⟩
26garfield = Cat("Garfield") # Uses default color27whiskers→ ⟨Cat D⟩ = Cat("Whiskers", "gray")2829print(f"{garfield.nameGarfield} is {garfield.colororange}")30print(f"{whiskers.nameWhiskers} is {whiskers.colorgray}")3132print("\n=== Multiple Initialization Patterns ===")3334class Person:35 def __init__(self, name, age=0, city="Unknown"):36 self.name = name37 self.age = age38 self.city = city39 40 def display(self):41 print(f"{self.name}, {self.age}, from {self.city}")4243# Various ways to create44p1 = Person("Alice")45p2 = Person("Bob", 25)outputGarfield is orange Whiskers is gray === Multiple Initialization Patterns ===self.name ← Alice, self.age ← 0, self.city ← Unknown
pass 1 of 434class Person:35 def __init__(self⟨Person E⟩, nameAlice, age0=0, cityUnknown="Unknown"):36 self.name→ Alice = nameAlice37 self.age→ 0 = age038 self.city→ Unknown = cityUnknownAll 4 passes — pass 1 is the card above pass selfnameagecityself.nameself.ageself.city1 ⟨Person E⟩ Alice 0 Unknown Alice 0 Unknown 2 ⟨Person F⟩ Bob 25 Unknown Bob 25 Unknown 3 ⟨Person G⟩ Carol 30 NYC Carol 30 NYC 4 ⟨Person H⟩ Dave 0 LA Dave 0 LA p1 ← ⟨Person E⟩
43# Various ways to create44p1→ ⟨Person E⟩ = Person("Alice")45p2 = Person("Bob", 25)46p3 = Person("Carol", 30, "NYC")p2 ← ⟨Person F⟩
44p1 = Person("Alice")45p2→ ⟨Person F⟩ = Person("Bob", 25)46p3 = Person("Carol", 30, "NYC")47p4 = Person("Dave", city="LA")p3 ← ⟨Person G⟩
45p2 = Person("Bob", 25)46p3→ ⟨Person G⟩ = Person("Carol", 30, "NYC")47p4 = Person("Dave", city="LA")p4 ← ⟨Person H⟩
46p3 = Person("Carol", 30, "NYC")47p4→ ⟨Person H⟩ = Person("Dave", city="LA")4849p1⟨Person E⟩.display()50p2.display()def display(self):
pass 1 of 440def display(self⟨Person E⟩):41 print(f"{self.nameAlice}, {self.age0}, from {self.cityUnknown}")outputAlice, 0, from UnknownAll 4 passes — pass 1 is the card above pass selfself.nameself.ageself.city1 ⟨Person E⟩ Alice 0 Unknown 2 ⟨Person F⟩ Bob 25 Unknown 3 ⟨Person G⟩ Carol 30 NYC 4 ⟨Person H⟩ Dave 0 LA p1.display()
49p1⟨Person E⟩.display()50p2⟨Person F⟩.display()51p3.display()p2.display()
49p1.display()50p2⟨Person F⟩.display()51p3⟨Person G⟩.display()52p4.display()p3.display()
50p2.display()51p3⟨Person G⟩.display()52p4⟨Person H⟩.display()p4.display()
51p3.display()52p4⟨Person H⟩.display()5354print("\n=== Computed Attributes ===")5556class Rectangle:57 def __init__(self, width, height):58 self.width = width59 self.height = height60 self.area = width * height61 self.perimeter = 2 * (width + height)6263rect = Rectangle(8, 2)64print(f"Rectangle {rect.width}x{rect.height}")output === Computed Attributes ===self.width ← 8, self.height ← 2, self.area ← 16, self.perimeter ← 20
56class Rectangle:57 def __init__(self⟨Rectangle I⟩, width8, height2):58 self.width→ 8 = width859 self.height→ 2 = height260 self.area→ 16 = width8 * height261 self.perimeter→ 20 = 2 * (width8 + height2)rect ← ⟨Rectangle I⟩
63rect→ ⟨Rectangle I⟩ = Rectangle(8, 2)64print(f"Rectangle {rect.width8}x{rect.height2}")65print(f"Area: {rect.area16}")66print(f"Perimeter: {rect.perimeter20}")outputRectangle 8x2 Area: 16 Perimeter: 20
Attributes set in __init__ are unique to each object.
Instance methods
Methods that operate on object data.
# Instance Methods
print("=== Instance Methods ===\n")
class Dog:
def __init__(self, name, energy=100):
self.name = name
self.energy = energy
def bark(self):
print(f"{self.name} says: Woof! Woof!")
def play(self):
if self.energy >= 20:
self.energy -= 20
print(f"{self.name} plays! Energy: {self.energy}")
else:
print(f"{self.name} is too tired to play")
def rest(self):
self.energy = min(100, self.energy + 30)
print(f"{self.name} rests. Energy: {self.energy}")
def status(self):
return f"{self.name}: {self.energy}/100 energy"
# Use methods
buddy = Dog("Buddy")
buddy.bark()
print(buddy.status())
print("\n=== Method Chaining State ===")
buddy.play()
buddy.play()
buddy.play()
buddy.play() # Energy check
buddy.rest()
print(buddy.status())
print("\n=== Methods Returning Values ===")
class Calculator:
def __init__(self, initial=0):
self.value = initial
def add(self, n):
self.value += n
return self.value
def multiply(self, n):
self.value *= n
return self.value
def reset(self):
self.value = 0
return self.value
calc = Calculator(10)
print(f"Start: {calc.value}")
print(f"Add 5: {calc.add(5)}")
print(f"Multiply by 3: {calc.multiply(3)}")
print(f"Current: {calc.value}")
print("\n=== Methods Calling Other Methods ===")
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
self.balance += amount
self._log_transaction("deposit", amount)
def withdraw(self, amount):
if amount <= self.balance:
self.balance -= amount
self._log_transaction("withdraw", amount)
return True
return False
def _log_transaction(self, type, amount):
print(f"[LOG] {self.owner}: {type} ${amount}, balance ${self.balance}")
account = BankAccount("Alice", 100)
account.deposit(50)
account.withdraw(30)
print("=== Instance Methods === ")
3print("=== Instance Methods ===\n")45class Dog:6 def __init__(self, name, energy=100):7 self.name = name8 self.energy = energy9 10 def bark(self): #?method11 print(f"{self.name} says: Woof! Woof!")12 13 def play(self): #?modifyattr14 if self.energy >= 20:15 self.energy -= 2016 print(f"{self.name} plays! Energy: {self.energy}")17 else:18 print(f"{self.name} is too tired to play")19 20 def rest(self):21 self.energy = min(100, self.energy + 30) #?capvalue22 print(f"{self.name} rests. Energy: {self.energy}")23 24 def status(self): #?returnmethod25 return f"{self.name}: {self.energy}/100 energy"2627# Use methods #?usemethods28buddy = Dog("Buddy")29buddy.bark()output=== Instance Methods ===self.name ← Buddy, self.energy ← 100
5class Dog:6 def __init__(self⟨Dog A⟩, nameBuddy, energy100=100):7 self.name→ Buddy = nameBuddy8 self.energy→ 100 = energy100buddy ← ⟨Dog A⟩
27# Use methods #?usemethods28buddy→ ⟨Dog A⟩ = Dog("Buddy")29buddy⟨Dog A⟩.bark()30print(buddy.status())def bark(self): #?method
10def bark(self⟨Dog A⟩): #?method11 print(f"{self.nameBuddy} says: Woof! Woof!")outputBuddy says: Woof! Woof!buddy.bark()
28buddy = Dog("Buddy")29buddy⟨Dog A⟩.bark()30print(buddy⟨Dog A⟩.status())def status(self): #?returnmethod
pass 1 of 224def status(self⟨Dog A⟩): #?returnmethod25 return f"{self.nameBuddy}: {self.energy100}/100 energy"print(buddy.status())
29buddy.bark()30print(buddy⟨Dog A⟩.status())3132print("\n=== Method Chaining State ===")3334buddy⟨Dog A⟩.play()35buddy.play()outputBuddy: 100/100 energy === Method Chaining State ===def play(self): #?modifyattr
pass 1 of 413def play(self⟨Dog A⟩): #?modifyattr14 if self.energy >= 20:15 self.energy -= 20self.energy ← 80
pass 1 of 413def play(self): #?modifyattr14 if self.energy100 >= 20:15 self.energy→ 80 -= 2016 print(f"{self.nameBuddy} plays! Energy: {self.energy80}")17 else:outputBuddy plays! Energy: 80All 4 passes — pass 1 is the card above pass self.energy1 100 → 80 2 80 → 60 3 60 → 40 4 40 → 20 buddy.play()
34buddy⟨Dog A⟩.play()35buddy⟨Dog A⟩.play()36buddy.play()buddy.play()
34buddy.play()35buddy⟨Dog A⟩.play()36buddy⟨Dog A⟩.play()37buddy.play() # Energy check #?energycheckbuddy.play()
35buddy.play()36buddy⟨Dog A⟩.play()37buddy⟨Dog A⟩.play() # Energy check #?energycheck38buddy.rest()buddy.play() # Energy check #?energycheck
36buddy.play()37buddy⟨Dog A⟩.play() # Energy check #?energycheck38buddy⟨Dog A⟩.rest()39print(buddy.status())self.energy ← 50
20def rest(self⟨Dog A⟩):21 self.energy→ 50 = min(100, self.energy + 30) #?capvalue22 print(f"{self.nameBuddy} rests. Energy: {self.energy50}")outputBuddy rests. Energy: 50buddy.rest()
37buddy.play() # Energy check #?energycheck38buddy⟨Dog A⟩.rest()39print(buddy⟨Dog A⟩.status())def status(self): #?returnmethod
pass 2 of 224def status(self⟨Dog A⟩): #?returnmethod25 return f"{self.nameBuddy}: {self.energy50}/100 energy"print(buddy.status())
38buddy.rest()39print(buddy⟨Dog A⟩.status())4041print("\n=== Methods Returning Values ===")4243class Calculator:44 def __init__(self, initial=0):45 self.value = initial46 47 def add(self, n): #?returnself48 self.value += n49 return self.value #?returnvalue50 51 def multiply(self, n):52 self.value *= n53 return self.value54 55 def reset(self):56 self.value = 057 return self.value5859calc = Calculator(10)60print(f"Start: {calc.value}")outputBuddy: 50/100 energy === Methods Returning Values ===self.value ← 10
43class Calculator:44 def __init__(self⟨Calculator B⟩, initial10=0):45 self.value→ 10 = initial10calc ← ⟨Calculator B⟩
59calc→ ⟨Calculator B⟩ = Calculator(10)60print(f"Start: {calc.value10}")61print(f"Add 5: {calc⟨Calculator B⟩.add(5)}")62print(f"Multiply by 3: {calc.multiply(3)}")outputStart: 10self.value ← 15
47def add(self⟨Calculator B⟩, n5): #?returnself48 self.value→ 15 += n549 return self.value15 #?returnvalueprint(f"Add 5: {calc.add(5)}")
60print(f"Start: {calc.value}")61print(f"Add 5: {calc⟨Calculator B⟩.add(5)}")62print(f"Multiply by 3: {calc⟨Calculator B⟩.multiply(3)}")63print(f"Current: {calc.value}")outputAdd 5: 15self.value ← 45
51def multiply(self⟨Calculator B⟩, n3):52 self.value→ 45 *= n353 return self.value45print(f"Multiply by 3: {calc.multiply(3)}")
61print(f"Add 5: {calc.add(5)}")62print(f"Multiply by 3: {calc⟨Calculator B⟩.multiply(3)}")63print(f"Current: {calc.value45}")6465print("\n=== Methods Calling Other Methods ===")6667class BankAccount:68 def __init__(self, owner, balance=0):69 self.owner = owner70 self.balance = balance71 72 def deposit(self, amount):73 self.balance += amount74 self._log_transaction("deposit", amount) #?callmethod75 76 def withdraw(self, amount):77 if amount <= self.balance:78 self.balance -= amount79 self._log_transaction("withdraw", amount)80 return True81 return False82 83 def _log_transaction(self, type, amount): #?internalmethod84 print(f"[LOG] {self.owner}: {type} ${amount}, balance ${self.balance}")8586account = BankAccount("Alice", 100)87account.deposit(50)outputMultiply by 3: 45 Current: 45 === Methods Calling Other Methods ===self.owner ← Alice, self.balance ← 100
67class BankAccount:68 def __init__(self⟨BankAccount C⟩, ownerAlice, balance100=0):69 self.owner→ Alice = ownerAlice70 self.balance→ 100 = balance100account ← ⟨BankAccount C⟩
86account→ ⟨BankAccount C⟩ = BankAccount("Alice", 100)87account⟨BankAccount C⟩.deposit(50)88account.withdraw(30)self.balance ← 150
72def deposit(self⟨BankAccount C⟩, amount50):73 self.balance→ 150 += amount5074 self._log_transaction("deposit", amount50) #?callmethoddef _log_transaction(self, type, amount): #?internalmethod
pass 1 of 273 self.balance += amount74 self._log_transaction("deposit", amount50) #?callmethod7576def withdraw(self, amount):77 if amount <= self.balance:78 self.balance -= amount79 self._log_transaction("withdraw", amount)80 return True81 return False8283def _log_transaction(self⟨BankAccount C⟩, typedeposit, amount50): #?internalmethod84 print(f"[LOG] {self.ownerAlice}: {type} ${amount50}, balance ${self.balance150}")output[LOG] Alice: deposit $50, balance $150account.deposit(50)
86account = BankAccount("Alice", 100)87account⟨BankAccount C⟩.deposit(50)88account⟨BankAccount C⟩.withdraw(30)89#@help methoddef withdraw(self, amount):
76def withdraw(self⟨BankAccount C⟩, amount30):77 if amount <= self.balance:78 self.balance -= amountself.balance ← 120
76def withdraw(self, amount):77 if amount30 <= self.balance150:78 self.balance→ 120 -= amount3079 self._log_transaction("withdraw", amount30)80 return Truedef _log_transaction(self, type, amount): #?internalmethod
pass 2 of 278 self.balance -= amount79 self._log_transaction("withdraw", amount30)80 return True81 return False8283def _log_transaction(self⟨BankAccount C⟩, typewithdraw, amount30): #?internalmethod84 print(f"[LOG] {self.ownerAlice}: {type} ${amount30}, balance ${self.balance120}")output[LOG] Alice: withdraw $30, balance $120account.withdraw(30)
87account.deposit(50)88account⟨BankAccount C⟩.withdraw(30)89#@help method
Methods take self as first parameter to access the object's attributes.
Multiple objects
Each object is independent with its own data.
# Working with Multiple Objects
print("=== Multiple Objects ===\n")
class Student:
def __init__(self, name, grade):
self.name = name
self.grade = grade
def study(self, hours):
improvement = hours * 2
self.grade = min(100, self.grade + improvement)
def display(self):
print(f"{self.name}: {self.grade}/100")
# Create multiple students
alice = Student("Alice", 85)
bob = Student("Bob", 72)
carol = Student("Carol", 90)
# Each has own state
print("Initial grades:")
alice.display()
bob.display()
carol.display()
print("\n=== Objects Act Independently ===")
# Changes to one don't affect others
bob.study(5) # Bob studies
carol.study(3)
print("\nAfter studying:")
alice.display() # Unchanged
bob.display() # Improved by 10
carol.display() # Improved by 6
print("\n=== Objects in a List ===")
class Product:
def __init__(self, name, price):
self.name = name
self.price = price
def apply_discount(self, percent):
self.price *= (1 - percent/100)
# Store objects in list
products = [
Product("Laptop", 999),
Product("Phone", 699),
Product("Tablet", 499)
]
# Process all objects
print("Original prices:")
for p in products:
print(f" {p.name}: ${p.price}")
# Apply discount to all
for p in products:
p.apply_discount(10)
print("\nAfter 10% discount:")
for p in products:
print(f" {p.name}: ${p.price:.2f}")
print("\n=== Objects Interacting ===")
class Player:
def __init__(self, name, health=100):
self.name = name
self.health = health
def attack(self, other, damage):
other.health -= damage
print(f"{self.name} attacks {other.name} for {damage} damage!")
print(f" {other.name}'s health: {other.health}")
def is_alive(self):
return self.health > 0
# Two players interact
hero = Player("Hero")
monster = Player("Dragon", 150)
hero.attack(monster, 30)
monster.attack(hero, 25)
hero.attack(monster, 40)
print(f"\nFinal: Hero={hero.health}, Dragon={monster.health}")
print("=== Multiple Objects === ")
3print("=== Multiple Objects ===\n")45class Student:6 def __init__(self, name, grade):7 self.name = name8 self.grade = grade9 10 def study(self, hours):11 improvement = hours * 2 #?improvement12 self.grade = min(100, self.grade + improvement)13 14 def display(self):15 print(f"{self.name}: {self.grade}/100")1617# Create multiple students #?multiplestudents18alice = Student("Alice", 85)19bob = Student("Bob", 72)output=== Multiple Objects ===self.name ← Alice, self.grade ← 85
pass 1 of 35class Student:6 def __init__(self⟨Student A⟩, nameAlice, grade85):7 self.name→ Alice = nameAlice8 self.grade→ 85 = grade85All 3 passes — pass 1 is the card above pass selfnamegradeself.nameself.grade1 ⟨Student A⟩ Alice 85 Alice 85 2 ⟨Student B⟩ Bob 72 Bob 72 3 ⟨Student C⟩ Carol 90 Carol 90 alice ← ⟨Student A⟩
17# Create multiple students #?multiplestudents18alice→ ⟨Student A⟩ = Student("Alice", 85)19bob = Student("Bob", 72)20carol = Student("Carol", 90)bob ← ⟨Student B⟩
18alice = Student("Alice", 85)19bob→ ⟨Student B⟩ = Student("Bob", 72)20carol = Student("Carol", 90)carol ← ⟨Student C⟩
19bob = Student("Bob", 72)20carol→ ⟨Student C⟩ = Student("Carol", 90)2122# Each has own state #?ownstate23print("Initial grades:")24alice⟨Student A⟩.display()25bob.display()outputInitial grades:def display(self):
pass 1 of 614def display(self⟨Student A⟩):15 print(f"{self.nameAlice}: {self.grade85}/100")outputAlice: 85/100All 6 passes — pass 1 is the card above pass selfself.nameself.grade1 ⟨Student A⟩ Alice 85 2 ⟨Student B⟩ Bob 72 3 ⟨Student C⟩ Carol 90 4 ⟨Student A⟩ Alice 85 5 ⟨Student B⟩ Bob 82 6 ⟨Student C⟩ Carol 96 alice.display()
23print("Initial grades:")24alice⟨Student A⟩.display()25bob⟨Student B⟩.display()26carol.display()bob.display()
24alice.display()25bob⟨Student B⟩.display()26carol⟨Student C⟩.display()carol.display()
25bob.display()26carol⟨Student C⟩.display()2728print("\n=== Objects Act Independently ===")2930# Changes to one don't affect others #?independent31bob⟨Student B⟩.study(5) # Bob studies32carol.study(3)output === Objects Act Independently ===improvement ← 10, self.grade ← 82
pass 1 of 210def study(self⟨Student B⟩, hours5):11 improvement→ 10 = hours5 * 2 #?improvement12 self.grade→ 82 = min(100, self.grade + improvement10)bob.study(5) # Bob studies
30# Changes to one don't affect others #?independent31bob⟨Student B⟩.study(5) # Bob studies32carol⟨Student C⟩.study(3)improvement ← 6, self.grade ← 96
pass 2 of 210def study(self⟨Student C⟩, hours3):11 improvement→ 6 = hours3 * 2 #?improvement12 self.grade→ 96 = min(100, self.grade + improvement6)carol.study(3)
31bob.study(5) # Bob studies32carol⟨Student C⟩.study(3)3334print("\nAfter studying:")35alice⟨Student A⟩.display() # Unchanged36bob.display() # Improved by 10output After studying:alice.display() # Unchanged
34print("\nAfter studying:")35alice⟨Student A⟩.display() # Unchanged36bob⟨Student B⟩.display() # Improved by 1037carol.display() # Improved by 6bob.display() # Improved by 10
35alice.display() # Unchanged36bob⟨Student B⟩.display() # Improved by 1037carol⟨Student C⟩.display() # Improved by 6carol.display() # Improved by 6
36bob.display() # Improved by 1037carol⟨Student C⟩.display() # Improved by 63839print("\n=== Objects in a List ===")4041class Product:42 def __init__(self, name, price):43 self.name = name44 self.price = price45 46 def apply_discount(self, percent):47 self.price *= (1 - percent/100)4849# Store objects in list #?objectlist50products = [51 Product("Laptop", 999),52 Product("Phone", 699),53 Product("Tablet", 499)54]output === Objects in a List ===self.name ← Laptop, self.price ← 999
pass 1 of 341class Product:42 def __init__(self⟨Product D⟩, nameLaptop, price999):43 self.name→ Laptop = nameLaptop44 self.price→ 999 = price999All 3 passes — pass 1 is the card above pass selfnamepriceself.nameself.price1 ⟨Product D⟩ Laptop 999 Laptop 999 2 ⟨Product E⟩ Phone 699 Phone 699 3 ⟨Product F⟩ Tablet 499 Tablet 499 products ← [⟨Product D⟩, ⟨Product E⟩, ⟨Product F⟩]
49# Store objects in list #?objectlist50products→ [⟨Product D⟩, ⟨Product E⟩, ⟨Product F⟩] = [51 Product("Laptop", 999),52 Product("Phone", 699),53 Product("Tablet", 499)54]5556# Process all objects #?processall57print("Original prices:")58for p in products:outputOriginal prices:for p in products:
pass 1 of 357print("Original prices:")58for p⟨Product D⟩ in products[⟨Product D⟩, ⟨Product E⟩, ⟨Product F⟩]:59 print(f" {p.nameLaptop}: ${p.price999}")output Laptop: $999All 3 passes — pass 1 is the card above pass pp.namep.price1 ⟨Product D⟩ Laptop 999 2 ⟨Product E⟩ Phone 699 3 ⟨Product F⟩ Tablet 499 for p in products:
pass 1 of 361# Apply discount to all #?bulkoperation62for p⟨Product D⟩ in products[⟨Product D⟩, ⟨Product E⟩, ⟨Product F⟩]:63 p⟨Product D⟩.apply_discount(10)All 3 passes — pass 1 is the card above pass p1 ⟨Product D⟩ 2 ⟨Product E⟩ 3 ⟨Product F⟩ self.price ← 899.1
pass 1 of 346def apply_discount(self⟨Product D⟩, percent10):47 self.price→ 899.1 *= (1 - percent10/100)All 3 passes — pass 1 is the card above pass selfself.price1 ⟨Product D⟩ 999 → 899.1 2 ⟨Product E⟩ 699 → 629.1 3 ⟨Product F⟩ 499 → 449.1 p.apply_discount(10)
62for p in products:63 p⟨Product D⟩.apply_discount(10)p.apply_discount(10)
62for p in products:63 p⟨Product E⟩.apply_discount(10)p.apply_discount(10)
62for p in products:63 p⟨Product F⟩.apply_discount(10)print(" After 10% discount:")
65print("\nAfter 10% discount:")66for p in products:output After 10% discount:for p in products:
pass 1 of 365print("\nAfter 10% discount:")66for p⟨Product D⟩ in products[⟨Product D⟩, ⟨Product E⟩, ⟨Product F⟩]:67 print(f" {p.nameLaptop}: ${p.price899.1:.2f}")output Laptop: $899.10All 3 passes — pass 1 is the card above pass pp.namep.price1 ⟨Product D⟩ Laptop 899.1 2 ⟨Product E⟩ Phone 629.1 3 ⟨Product F⟩ Tablet 449.1 print(" === Objects Interacting ===")
69print("\n=== Objects Interacting ===")7071class Player:72 def __init__(self, name, health=100):73 self.name = name74 self.health = health75 76 def attack(self, other, damage): #?interact77 other.health -= damage #?modifyother78 print(f"{self.name} attacks {other.name} for {damage} damage!")79 print(f" {other.name}'s health: {other.health}")80 81 def is_alive(self):82 return self.health > 08384# Two players interact #?twoplayers85hero = Player("Hero")86monster = Player("Dragon", 150)output === Objects Interacting ===self.name ← Hero, self.health ← 100
pass 1 of 271class Player:72 def __init__(self⟨Player G⟩, nameHero, health100=100):73 self.name→ Hero = nameHero74 self.health→ 100 = health100hero ← ⟨Player G⟩
84# Two players interact #?twoplayers85hero→ ⟨Player G⟩ = Player("Hero")86monster = Player("Dragon", 150)self.name ← Dragon, self.health ← 150
pass 2 of 271class Player:72 def __init__(self⟨Player H⟩, nameDragon, health150=100):73 self.name→ Dragon = nameDragon74 self.health→ 150 = health150monster ← ⟨Player H⟩
85hero = Player("Hero")86monster→ ⟨Player H⟩ = Player("Dragon", 150)8788hero⟨Player G⟩.attack(monster⟨Player H⟩, 30)89monster.attack(hero, 25)other.health ← 120
pass 1 of 376def attack(self⟨Player G⟩, other⟨Player H⟩, damage30): #?interact77 other.health→ 120 -= damage30 #?modifyother78 print(f"{self.nameHero} attacks {other.nameDragon} for {damage30} damage!")79 print(f" {other.nameDragon}'s health: {other.health120}")outputHero attacks Dragon for 30 damage! Dragon's health: 120All 3 passes — pass 1 is the card above pass selfotherdamageself.nameother.nameother.health1 ⟨Player G⟩ ⟨Player H⟩ 30 Hero Dragon 150 → 120 2 ⟨Player H⟩ ⟨Player G⟩ 25 Dragon Hero 100 → 75 3 ⟨Player G⟩ ⟨Player H⟩ 40 Hero Dragon 120 → 80 hero.attack(monster, 30)
88hero⟨Player G⟩.attack(monster⟨Player H⟩, 30)89monster⟨Player H⟩.attack(hero⟨Player G⟩, 25)90hero.attack(monster, 40)monster.attack(hero, 25)
88hero.attack(monster, 30)89monster⟨Player H⟩.attack(hero⟨Player G⟩, 25)90hero⟨Player G⟩.attack(monster⟨Player H⟩, 40)hero.attack(monster, 40)
89monster.attack(hero, 25)90hero⟨Player G⟩.attack(monster⟨Player H⟩, 40)9192print(f"\nFinal: Hero={hero.health75}, Dragon={monster.health80}")93#@help improvementoutput Final: Hero=75, Dragon=80
Changes to one object don't affect others. Each has its own memory.
Classes with business logic
Methods that compute and transform data.
# Classes with Business Logic
print("=== Shopping Cart ===\n")
class ShoppingCart:
def __init__(self):
self.items = []
def add_item(self, name, price, quantity=1):
item = {"name": name, "price": price, "qty": quantity}
self.items.append(item)
print(f"Added {quantity}x {name} @ ${price}")
def remove_item(self, name):
for item in self.items:
if item["name"] == name:
self.items.remove(item)
print(f"Removed {name}")
return True
print(f"{name} not found")
return False
def get_total(self):
total = 0
for item in self.items:
total += item["price"] * item["qty"]
return total
def display(self):
print("\n--- Cart Contents ---")
for item in self.items:
subtotal = item["price"] * item["qty"]
print(f" {item['name']}: {item['qty']} x ${item['price']} = ${subtotal}")
print(f"Total: ${self.get_total():.2f}")
# Use the cart
cart = ShoppingCart()
cart.add_item("Apple", 0.50, 5)
cart.add_item("Bread", 2.50)
cart.add_item("Milk", 3.00, 2)
cart.display()
cart.remove_item("Bread")
cart.display()
print("\n=== Temperature Converter ===")
class Temperature:
def __init__(self, celsius=0):
self.celsius = celsius
@property
def fahrenheit(self):
return self.celsius * 9/5 + 32
@property
def kelvin(self):
return self.celsius + 273.15
def set_fahrenheit(self, f):
self.celsius = (f - 32) * 5/9
def describe(self):
if self.celsius < 0:
return "Freezing"
elif self.celsius < 15:
return "Cold"
elif self.celsius < 25:
return "Comfortable"
else:
return "Hot"
temp = Temperature(25)
print(f"{temp.celsius}°C = {temp.fahrenheit}°F = {temp.kelvin}K")
print(f"Feeling: {temp.describe()}")
temp.set_fahrenheit(32) # Set from Fahrenheit
print(f"\n32°F = {temp.celsius:.1f}°C ({temp.describe()})")
print("\n=== Counter with History ===")
class Counter:
def __init__(self, start=0):
self.value = start
self.history = [start]
def increment(self, amount=1):
self.value += amount
self.history.append(self.value)
def decrement(self, amount=1):
self.value -= amount
self.history.append(self.value)
def undo(self):
if len(self.history) > 1:
self.history.pop()
self.value = self.history[-1]
counter = Counter()
counter.increment(5)
counter.increment(3)
counter.decrement(2)
print(f"Value: {counter.value}")
print(f"History: {counter.history}")
counter.undo()
print(f"After undo: {counter.value}")
print(f"History: {counter.history}")
print("=== Shopping Cart === ")
3print("=== Shopping Cart ===\n")45class ShoppingCart:6 def __init__(self):7 self.items = [] #?initlist8 9 def add_item(self, name, price, quantity=1): #?additem10 item = {"name": name, "price": price, "qty": quantity} #?itemdict11 self.items.append(item)12 print(f"Added {quantity}x {name} @ ${price}")13 14 def remove_item(self, name):15 for item in self.items: #?searchitem16 if item["name"] == name:17 self.items.remove(item)18 print(f"Removed {name}")19 return True20 print(f"{name} not found")21 return False22 23 def get_total(self): #?gettotal24 total = 025 for item in self.items:26 total += item["price"] * item["qty"]27 return total28 29 def display(self):30 print("\n--- Cart Contents ---")31 for item in self.items:32 subtotal = item["price"] * item["qty"]33 print(f" {item['name']}: {item['qty']} x ${item['price']} = ${subtotal}")34 print(f"Total: ${self.get_total():.2f}")3536# Use the cart #?usecart37cart = ShoppingCart()38cart.add_item("Apple", 0.50, 5)output=== Shopping Cart ===self.items ← []
5class ShoppingCart:6 def __init__(self⟨ShoppingCart A⟩):7 self.items→ [] = [] #?initlistcart ← ⟨ShoppingCart A⟩
36# Use the cart #?usecart37cart→ ⟨ShoppingCart A⟩ = ShoppingCart()38cart⟨ShoppingCart A⟩.add_item("Apple", 0.50, 5)39cart.add_item("Bread", 2.50)item ← {'name': 'Apple', 'price': 0.5, 'qty': 5}, self.items ← [{'name': 'Apple', 'price': 0.5, 'qty': 5}]
pass 1 of 39def add_item(self⟨ShoppingCart A⟩, nameApple, price0.5, quantity5=1): #?additem10 item→ {'name': 'Apple', 'price': 0.5, 'qty': 5} = {"name": nameApple, "price": price0.5, "qty": quantity5} #?itemdict11 self.items→ [{'name': 'Apple', 'price': 0.5, 'qty': 5}].append(item{'name': 'Apple', 'price': 0.5, 'qty': 5})12 print(f"Added {quantity5}x {nameApple} @ ${price0.5}")outputAdded 5x Apple @ $0.5All 3 passes — pass 1 is the card above pass namepricequantityitemself.items1 Apple 0.5 5 {'name': 'Apple', 'price': 0.5, 'qty': 5} [] → [{'name': 'Apple', 'price': 0.5, 'qty': 5}] 2 Bread 2.5 1 {'name': 'Bread', 'price': 2.5, 'qty': 1} [{'name': 'Apple', 'price': 0.5, 'qty': 5}] → [{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Bread', 'price': 2.5, 'qty': 1}] 3 Milk 3.0 2 {'name': 'Milk', 'price': 3.0, 'qty': 2} [{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Bread', 'price': 2.5, 'qty': 1}] → [{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Bread', 'price': 2.5, 'qty': 1}, {'name': 'Milk', 'price': 3.0, 'qty': 2}] cart.add_item("Apple", 0.50, 5)
37cart = ShoppingCart()38cart⟨ShoppingCart A⟩.add_item("Apple", 0.50, 5)39cart⟨ShoppingCart A⟩.add_item("Bread", 2.50)40cart.add_item("Milk", 3.00, 2)cart.add_item("Bread", 2.50)
38cart.add_item("Apple", 0.50, 5)39cart⟨ShoppingCart A⟩.add_item("Bread", 2.50)40cart⟨ShoppingCart A⟩.add_item("Milk", 3.00, 2)41cart.display()cart.add_item("Milk", 3.00, 2)
39cart.add_item("Bread", 2.50)40cart⟨ShoppingCart A⟩.add_item("Milk", 3.00, 2)41cart⟨ShoppingCart A⟩.display()def display(self):
pass 1 of 229def display(self⟨ShoppingCart A⟩):30 print("\n--- Cart Contents ---")31 for item in self.items:output --- Cart Contents ---subtotal ← 2.5
pass 1 of 530print("\n--- Cart Contents ---")31for item{'name': 'Apple', 'price': 0.5, 'qty': 5} in self.items[{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Bread', 'price': 2.5, 'qty': 1}, {'name': 'Milk', 'price': 3.0, 'qty': 2}]:32 subtotal→ 2.5 = item["price"]0.5 * item["qty"]533 print(f" {item['name']Apple}: {item['qty']5} x ${item['price']0.5} = ${subtotal2.5}")34print(f"Total: ${self.get_total():.2f}")output Apple: 5 x $0.5 = $2.5All 5 passes — pass 1 is the card above pass itemself.itemsitem[”price”]item[”qty”]item[’name’]item[’qty’]item[’price’]subtotal1 {'name': 'Apple', 'price': 0.5, 'qty': 5} [{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Bread', 'price': 2.5, 'qty': 1}, {'name': 'Milk', 'price': 3.0, 'qty': 2}] 0.5 5 Apple 5 0.5 2.5 2 {'name': 'Bread', 'price': 2.5, 'qty': 1} [{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Bread', 'price': 2.5, 'qty': 1}, {'name': 'Milk', 'price': 3.0, 'qty': 2}] 2.5 1 Bread 1 2.5 2.5 3 {'name': 'Milk', 'price': 3.0, 'qty': 2} [{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Bread', 'price': 2.5, 'qty': 1}, {'name': 'Milk', 'price': 3.0, 'qty': 2}] 3.0 2 Milk 2 3.0 6.0 4 {'name': 'Apple', 'price': 0.5, 'qty': 5} [{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Milk', 'price': 3.0, 'qty': 2}] 0.5 5 Apple 5 0.5 2.5 5 {'name': 'Milk', 'price': 3.0, 'qty': 2} [{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Milk', 'price': 3.0, 'qty': 2}] 3.0 2 Milk 2 3.0 6.0 print(f"Total: ${self.get_total():.2f}")
33 print(f" {item['name']}: {item['qty']} x ${item['price']} = ${subtotal}")34print(f"Total: ${self.get_total():.2f}")total ← 0
pass 1 of 223def get_total(self⟨ShoppingCart A⟩): #?gettotal24 total→ 0 = 025 for item in self.items:total ← 2.5
pass 1 of 524total = 025for item{'name': 'Apple', 'price': 0.5, 'qty': 5} in self.items[{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Bread', 'price': 2.5, 'qty': 1}, {'name': 'Milk', 'price': 3.0, 'qty': 2}]:26 total→ 2.5 += item["price"]0.5 * item["qty"]527return totalAll 5 passes — pass 1 is the card above pass itemself.itemsitem[”price”]item[”qty”]total1 {'name': 'Apple', 'price': 0.5, 'qty': 5} [{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Bread', 'price': 2.5, 'qty': 1}, {'name': 'Milk', 'price': 3.0, 'qty': 2}] 0.5 5 0 → 2.5 2 {'name': 'Bread', 'price': 2.5, 'qty': 1} [{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Bread', 'price': 2.5, 'qty': 1}, {'name': 'Milk', 'price': 3.0, 'qty': 2}] 2.5 1 2.5 → 5.0 3 {'name': 'Milk', 'price': 3.0, 'qty': 2} [{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Bread', 'price': 2.5, 'qty': 1}, {'name': 'Milk', 'price': 3.0, 'qty': 2}] 3.0 2 5.0 → 11.0 4 {'name': 'Apple', 'price': 0.5, 'qty': 5} [{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Milk', 'price': 3.0, 'qty': 2}] 0.5 5 0 → 2.5 5 {'name': 'Milk', 'price': 3.0, 'qty': 2} [{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Milk', 'price': 3.0, 'qty': 2}] 3.0 2 2.5 → 8.5 return total
26 total += item["price"] * item["qty"]27return total11.0print(f"Total: ${self.get_total():.2f}")
33 print(f" {item['name']}: {item['qty']} x ${item['price']} = ${subtotal}")34print(f"Total: ${self.get_total():.2f}")outputTotal: $11.00cart.display()
40cart.add_item("Milk", 3.00, 2)41cart⟨ShoppingCart A⟩.display()4243cart⟨ShoppingCart A⟩.remove_item("Bread")44cart.display()def remove_item(self, name):
14def remove_item(self⟨ShoppingCart A⟩, nameBread):15 for item in self.items: #?searchitem16 if item["name"] == name:for item in self.items: #?searchitem
pass 1 of 214def remove_item(self, name):15 for item{'name': 'Apple', 'price': 0.5, 'qty': 5} in self.items[{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Bread', 'price': 2.5, 'qty': 1}, {'name': 'Milk', 'price': 3.0, 'qty': 2}]: #?searchitem16 if item["name"] == name:17 self.items.remove(item)for item in self.items: #?searchitem
pass 2 of 214def remove_item(self, name):15 for item{'name': 'Bread', 'price': 2.5, 'qty': 1} in self.items[{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Bread', 'price': 2.5, 'qty': 1}, {'name': 'Milk', 'price': 3.0, 'qty': 2}]: #?searchitem16 if item["name"] == name:17 self.items.remove(item)self.items ← [{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Milk', 'price': 3.0, 'qty': 2}]
15for item in self.items: #?searchitem16 if item["name"]Bread == nameBread:17 self.items→ [{'name': 'Apple', 'price': 0.5, 'qty': 5}, {'name': 'Milk', 'price': 3.0, 'qty': 2}].remove(item{'name': 'Bread', 'price': 2.5, 'qty': 1})18 print(f"Removed {nameBread}")19 return True20print(f"{name} not found")outputRemoved Breadcart.remove_item("Bread")
43cart⟨ShoppingCart A⟩.remove_item("Bread")44cart⟨ShoppingCart A⟩.display()def display(self):
pass 2 of 229def display(self⟨ShoppingCart A⟩):30 print("\n--- Cart Contents ---")31 for item in self.items:output --- Cart Contents ---print(f"Total: ${self.get_total():.2f}")
33 print(f" {item['name']}: {item['qty']} x ${item['price']} = ${subtotal}")34print(f"Total: ${self.get_total():.2f}")total ← 0
pass 2 of 223def get_total(self⟨ShoppingCart A⟩): #?gettotal24 total→ 0 = 025 for item in self.items:return total
26 total += item["price"] * item["qty"]27return total8.5print(f"Total: ${self.get_total():.2f}")
33 print(f" {item['name']}: {item['qty']} x ${item['price']} = ${subtotal}")34print(f"Total: ${self.get_total():.2f}")outputTotal: $8.50cart.display()
43cart.remove_item("Bread")44cart⟨ShoppingCart A⟩.display()4546print("\n=== Temperature Converter ===")4748class Temperature:49 def __init__(self, celsius=0): #?tempinit50 self.celsius = celsius51 52 @property53 def fahrenheit(self): #?property54 return self.celsius * 9/5 + 3255 56 @property57 def kelvin(self):58 return self.celsius + 273.1559 60 def set_fahrenheit(self, f): #?setf61 self.celsius = (f - 32) * 5/962 63 def describe(self): #?describe64 if self.celsius < 0:65 return "Freezing"66 elif self.celsius < 15:67 return "Cold"68 elif self.celsius < 25:69 return "Comfortable"70 else:71 return "Hot"7273temp = Temperature(25)74print(f"{temp.celsius}°C = {temp.fahrenheit}°F = {temp.kelvin}K")output === Temperature Converter ===self.celsius ← 25
48class Temperature:49 def __init__(self⟨Temperature B⟩, celsius25=0): #?tempinit50 self.celsius→ 25 = celsius25temp ← ⟨Temperature B⟩
73temp→ ⟨Temperature B⟩ = Temperature(25)74print(f"{temp.celsius25}°C = {temp.fahrenheit77.0}°F = {temp.kelvin298.15}K")75print(f"Feeling: {temp.describe()}")def fahrenheit(self): #?property
52@property53def fahrenheit(self⟨Temperature B⟩): #?property54 return self.celsius25 * 9/5 + 32def kelvin(self):
56@property57def kelvin(self⟨Temperature B⟩):58 return self.celsius25 + 273.15print(f"{temp.celsius}°C = {temp.fahrenheit}°F = {temp.kelvin}K")
73temp = Temperature(25)74print(f"{temp.celsius25}°C = {temp.fahrenheit77.0}°F = {temp.kelvin298.15}K")75print(f"Feeling: {temp⟨Temperature B⟩.describe()}")output25°C = 77.0°F = 298.15Kdef describe(self): #?describe
pass 1 of 263def describe(self⟨Temperature B⟩): #?describe64 if self.celsius < 0:65 return "Freezing"print(f"Feeling: {temp.describe()}")
74print(f"{temp.celsius}°C = {temp.fahrenheit}°F = {temp.kelvin}K")75print(f"Feeling: {temp⟨Temperature B⟩.describe()}")7677temp⟨Temperature B⟩.set_fahrenheit(32) # Set from Fahrenheit #?setfuse78print(f"\n32°F = {temp.celsius:.1f}°C ({temp.describe()})")outputFeeling: Hotself.celsius ← 0.0
60def set_fahrenheit(self⟨Temperature B⟩, f32): #?setf61 self.celsius→ 0.0 = (f32 - 32) * 5/9temp.set_fahrenheit(32) # Set from Fahrenheit #?setfuse
77temp⟨Temperature B⟩.set_fahrenheit(32) # Set from Fahrenheit #?setfuse78print(f"\n32°F = {temp.celsius0.0:.1f}°C ({temp⟨Temperature B⟩.describe()})")def describe(self): #?describe
pass 2 of 263def describe(self⟨Temperature B⟩): #?describe64 if self.celsius < 0:65 return "Freezing"elif self.celsius < 15:
65 return "Freezing"66elif self.celsius0.0 < 15:67 return "Cold"68elif self.celsius < 25:print(f" 32°F = {temp.celsius:.1f}°C ({temp.describe()})")
77temp.set_fahrenheit(32) # Set from Fahrenheit #?setfuse78print(f"\n32°F = {temp.celsius0.0:.1f}°C ({temp⟨Temperature B⟩.describe()})")7980print("\n=== Counter with History ===")8182class Counter:83 def __init__(self, start=0):84 self.value = start85 self.history = [start] #?history86 87 def increment(self, amount=1):88 self.value += amount89 self.history.append(self.value) #?record90 91 def decrement(self, amount=1):92 self.value -= amount93 self.history.append(self.value)94 95 def undo(self): #?undo96 if len(self.history) > 1:97 self.history.pop()98 self.value = self.history[-1]99100counter = Counter()101counter.increment(5)output 32°F = 0.0°C (Cold) === Counter with History ===self.value ← 0, self.history ← [0]
82class Counter:83 def __init__(self⟨Counter C⟩, start0=0):84 self.value→ 0 = start085 self.history→ [0] = [start0] #?historycounter ← ⟨Counter C⟩
100counter→ ⟨Counter C⟩ = Counter()101counter⟨Counter C⟩.increment(5)102counter.increment(3)self.value ← 5, self.history ← [0, 5]
pass 1 of 287def increment(self⟨Counter C⟩, amount5=1):88 self.value→ 5 += amount589 self.history→ [0, 5].append(self.value5) #?recordcounter.increment(5)
100counter = Counter()101counter⟨Counter C⟩.increment(5)102counter⟨Counter C⟩.increment(3)103counter.decrement(2)self.value ← 8, self.history ← [0, 5, 8]
pass 2 of 287def increment(self⟨Counter C⟩, amount3=1):88 self.value→ 8 += amount389 self.history→ [0, 5, 8].append(self.value8) #?recordcounter.increment(3)
101counter.increment(5)102counter⟨Counter C⟩.increment(3)103counter⟨Counter C⟩.decrement(2)104print(f"Value: {counter.value}")self.value ← 6, self.history ← [0, 5, 8, 6]
91def decrement(self⟨Counter C⟩, amount2=1):92 self.value→ 6 -= amount293 self.history→ [0, 5, 8, 6].append(self.value6)counter.decrement(2)
102counter.increment(3)103counter⟨Counter C⟩.decrement(2)104print(f"Value: {counter.value6}")105print(f"History: {counter.history[0, 5, 8, 6]}")106107counter⟨Counter C⟩.undo()108print(f"After undo: {counter.value}")outputValue: 6 History: [0, 5, 8, 6]def undo(self): #?undo
95def undo(self⟨Counter C⟩): #?undo96 if len(self.history) > 1:97 self.history.pop()self.history ← [0, 5, 8], self.value ← 8
95def undo(self): #?undo96 if len(self.history[0, 5, 8, 6]) > 1:97 self.history→ [0, 5, 8].pop()98 self.value→ 8 = self.history[-1]8counter.undo()
107counter⟨Counter C⟩.undo()108print(f"After undo: {counter.value8}")109print(f"History: {counter.history[0, 5, 8]}")110#@help initlistoutputAfter undo: 8 History: [0, 5, 8]
Classes can encapsulate complex logic, not just data storage.
Exercise: practical.py
Build a complete class with attributes, methods, and logic