Week 2 Assignment
Variant 1: Library Book
A library needs a LibraryBook class to track its books. Each book has a title, total copies, and borrowed copies.
titleis read-only (protected attribute, getter only).total_copiesmust be at least1— otherwise raiseValueErrorwith"Total copies must be at least 1". Use a property; route initial value through the setter.borrowed_copies(default0) cannot be negative ("Borrowed copies cannot be negative") and cannot exceedtotal_copies("Borrowed copies cannot exceed total copies"). Use a property; route initial value through the setter.- Read-only computed property
available_copiesreturnstotal_copies - borrowed_copies. - Method
borrow(amount)increases borrowed copies. Amount must be positive ("Borrow amount must be positive") and not exceed available copies ("Not enough available copies"). - Method
return_book(amount)decreases borrowed copies. Amount must be positive ("Return amount must be positive") and not exceed borrowed copies ("Cannot return more than borrowed").
Input
b = LibraryBook("Python Basics", 5)
print(b.title, b.available_copies)
b.borrow(3)
print(b.borrowed_copies, b.available_copies)
b.return_book(1)
print(b.borrowed_copies)
try:
b.borrow(4)
except ValueError as e:
print(e)
try:
b.title = "X"
except AttributeError:
print("Cannot change title")
Expected Output
Python Basics 5
3 2
2
Not enough available copies
Cannot change title
Variant 2: Gym Membership
A fitness center needs a GymMembership class. Each membership has a member name, monthly fee, and remaining months.
member_nameis read-only (protected attribute, getter only).monthly_feemust be positive ("Monthly fee must be positive"). Use a property; route initial value through the setter.remaining_monthsmust be between1and36inclusive ("Remaining months must be between 1 and 36"). Use a property; route initial value through the setter.- Read-only computed property
total_costreturnsmonthly_fee * remaining_months. - Method
extend(months)adds months. Must be positive ("Extension must be positive"). Result must not exceed36("Cannot exceed 36 months"). - Method
apply_discount(percent)reduces the monthly fee by the given percentage. Percent must be between1and50inclusive ("Discount must be between 1 and 50").
Input
g = GymMembership("Bobur", 50.0, 12)
print(g.member_name, g.total_cost)
g.extend(6)
print(g.remaining_months)
g.apply_discount(10)
print(g.monthly_fee, g.total_cost)
try:
g.extend(25)
except ValueError as e:
print(e)
try:
g.member_name = "X"
except AttributeError:
print("Cannot change member name")
Expected Output
Bobur 600.0
18
45.0 810.0
Cannot exceed 36 months
Cannot change member name
Variant 3: Parking Lot
A parking system needs a ParkingLot class. Each lot has a name, total spaces, and occupied spaces.
nameis read-only (protected attribute, getter only).total_spacesmust be at least1("Total spaces must be at least 1"). Use a property; route initial value through the setter.occupied_spaces(default0) cannot be negative ("Occupied spaces cannot be negative") and cannot exceedtotal_spaces("Occupied spaces cannot exceed total spaces"). Use a property; route initial value through the setter.- Read-only computed property
free_spacesreturnstotal_spaces - occupied_spaces. - Read-only computed property
occupancy_ratereturns the occupancy percentage as a float rounded to one decimal place. - Method
park(cars)increases occupied spaces. Must be positive ("Number of cars must be positive") and not exceed free spaces ("Not enough free spaces"). - Method
leave(cars)decreases occupied spaces. Must be positive ("Number of cars must be positive") and not exceed occupied spaces ("Cannot remove more cars than parked").
Input
lot = ParkingLot("Central", 30)
print(lot.name, lot.free_spaces, lot.occupancy_rate)
lot.park(20)
print(lot.occupied_spaces, lot.occupancy_rate)
lot.leave(5)
print(lot.free_spaces)
try:
lot.park(20)
except ValueError as e:
print(e)
try:
lot.name = "X"
except AttributeError:
print("Cannot change lot name")
Expected Output
Central 30 0.0
20 66.7
15
Not enough free spaces
Cannot change lot name
Variant 4: Concert Hall
A venue management system needs a ConcertHall class. Each hall has a name, total seats, and booked seats.
nameis read-only (protected attribute, getter only).total_seatsmust be at least1("Total seats must be at least 1"). Use a property; route initial value through the setter.booked_seats(default0) cannot be negative ("Booked seats cannot be negative") and cannot exceedtotal_seats("Booked seats cannot exceed total seats"). Use a property; route initial value through the setter.- Read-only computed property
available_seatsreturnstotal_seats - booked_seats. - Read-only computed property
booking_ratereturns the booking percentage as a float rounded to one decimal place. - Method
reserve(seats)increases booked seats. Must be positive ("Number of seats must be positive") and not exceed available seats ("Not enough available seats"). - Method
cancel(seats)decreases booked seats. Must be positive ("Number of seats must be positive") and not exceed booked seats ("Cannot cancel more than booked").
Input
h = ConcertHall("Grand", 200)
print(h.name, h.available_seats, h.booking_rate)
h.reserve(150)
print(h.booked_seats, h.booking_rate)
h.cancel(30)
print(h.available_seats)
try:
h.reserve(100)
except ValueError as e:
print(e)
try:
h.name = "X"
except AttributeError:
print("Cannot change hall name")
Expected Output
Grand 200 0.0
150 75.0
80
Not enough available seats
Cannot change hall name
Variant 5: Warehouse
A logistics company needs a Warehouse class. Each warehouse has a name, total capacity (in crates), and stored crates.
nameis read-only (protected attribute, getter only).total_capacitymust be at least1("Total capacity must be at least 1"). Use a property; route initial value through the setter.stored_crates(default0) cannot be negative ("Stored crates cannot be negative") and cannot exceedtotal_capacity("Stored crates cannot exceed total capacity"). Use a property; route initial value through the setter.- Read-only computed property
free_spacereturnstotal_capacity - stored_crates. - Read-only computed property
usage_ratereturns the usage percentage as a float rounded to one decimal place. - Method
store(crates)increases stored crates. Must be positive ("Number of crates must be positive") and not exceed free space ("Not enough free space"). - Method
ship(crates)decreases stored crates. Must be positive ("Number of crates must be positive") and not exceed stored crates ("Cannot ship more than stored").
Input
w = Warehouse("East", 500)
print(w.name, w.free_space, w.usage_rate)
w.store(350)
print(w.stored_crates, w.usage_rate)
w.ship(100)
print(w.free_space)
try:
w.store(300)
except ValueError as e:
print(e)
try:
w.name = "X"
except AttributeError:
print("Cannot change warehouse name")
Expected Output
East 500 0.0
350 70.0
250
Not enough free space
Cannot change warehouse name
Variant 6: Hotel Floor
A hotel system needs a HotelFloor class. Each floor has a name, total rooms, and occupied rooms.
nameis read-only (protected attribute, getter only).total_roomsmust be at least1("Total rooms must be at least 1"). Use a property; route initial value through the setter.occupied_rooms(default0) cannot be negative ("Occupied rooms cannot be negative") and cannot exceedtotal_rooms("Occupied rooms cannot exceed total rooms"). Use a property; route initial value through the setter.- Read-only computed property
vacant_roomsreturnstotal_rooms - occupied_rooms. - Read-only computed property
occupancy_ratereturns the occupancy percentage as a float rounded to one decimal place. - Method
check_in(rooms)increases occupied rooms. Must be positive ("Number of rooms must be positive") and not exceed vacant rooms ("Not enough vacant rooms"). - Method
check_out(rooms)decreases occupied rooms. Must be positive ("Number of rooms must be positive") and not exceed occupied rooms ("Cannot check out more than occupied").
Input
f = HotelFloor("Floor 3", 40)
print(f.name, f.vacant_rooms, f.occupancy_rate)
f.check_in(25)
print(f.occupied_rooms, f.occupancy_rate)
f.check_out(10)
print(f.vacant_rooms)
try:
f.check_in(30)
except ValueError as e:
print(e)
try:
f.name = "X"
except AttributeError:
print("Cannot change floor name")
Expected Output
Floor 3 40 0.0
25 62.5
25
Not enough vacant rooms
Cannot change floor name
Variant 7: Swimming Pool
A sports complex needs a SwimmingPool class. Each pool has a name, total lanes, and occupied lanes.
nameis read-only (protected attribute, getter only).total_lanesmust be at least1("Total lanes must be at least 1"). Use a property; route initial value through the setter.occupied_lanes(default0) cannot be negative ("Occupied lanes cannot be negative") and cannot exceedtotal_lanes("Occupied lanes cannot exceed total lanes"). Use a property; route initial value through the setter.- Read-only computed property
free_lanesreturnstotal_lanes - occupied_lanes. - Read-only computed property
occupancy_ratereturns the occupancy percentage as a float rounded to one decimal place. - Method
assign(lanes)increases occupied lanes. Must be positive ("Number of lanes must be positive") and not exceed free lanes ("Not enough free lanes"). - Method
release(lanes)decreases occupied lanes. Must be positive ("Number of lanes must be positive") and not exceed occupied lanes ("Cannot release more than occupied").
Input
p = SwimmingPool("Olympic", 8)
print(p.name, p.free_lanes, p.occupancy_rate)
p.assign(6)
print(p.occupied_lanes, p.occupancy_rate)
p.release(2)
print(p.free_lanes)
try:
p.assign(5)
except ValueError as e:
print(e)
try:
p.name = "X"
except AttributeError:
print("Cannot change pool name")
Expected Output
Olympic 8 0.0
6 75.0
4
Not enough free lanes
Cannot change pool name
Variant 8: Server Rack
A data center needs a ServerRack class. Each rack has a name, total slots, and used slots.
nameis read-only (protected attribute, getter only).total_slotsmust be at least1("Total slots must be at least 1"). Use a property; route initial value through the setter.used_slots(default0) cannot be negative ("Used slots cannot be negative") and cannot exceedtotal_slots("Used slots cannot exceed total slots"). Use a property; route initial value through the setter.- Read-only computed property
free_slotsreturnstotal_slots - used_slots. - Read-only computed property
usage_ratereturns the usage percentage as a float rounded to one decimal place. - Method
install(servers)increases used slots. Must be positive ("Number of servers must be positive") and not exceed free slots ("Not enough free slots"). - Method
remove(servers)decreases used slots. Must be positive ("Number of servers must be positive") and not exceed used slots ("Cannot remove more than installed").
Input
r = ServerRack("Rack-A1", 42)
print(r.name, r.free_slots, r.usage_rate)
r.install(30)
print(r.used_slots, r.usage_rate)
r.remove(6)
print(r.free_slots)
try:
r.install(20)
except ValueError as e:
print(e)
try:
r.name = "X"
except AttributeError:
print("Cannot change rack name")
Expected Output
Rack-A1 42 0.0
30 71.4
18
Not enough free slots
Cannot change rack name
Variant 9: Classroom
A school system needs a Classroom class. Each classroom has a name, total desks, and occupied desks.
nameis read-only (protected attribute, getter only).total_desksmust be at least1("Total desks must be at least 1"). Use a property; route initial value through the setter.occupied_desks(default0) cannot be negative ("Occupied desks cannot be negative") and cannot exceedtotal_desks("Occupied desks cannot exceed total desks"). Use a property; route initial value through the setter.- Read-only computed property
empty_desksreturnstotal_desks - occupied_desks. - Read-only computed property
fill_ratereturns the fill percentage as a float rounded to one decimal place. - Method
seat(students)increases occupied desks. Must be positive ("Number of students must be positive") and not exceed empty desks ("Not enough empty desks"). - Method
dismiss(students)decreases occupied desks. Must be positive ("Number of students must be positive") and not exceed occupied desks ("Cannot dismiss more than seated").
Input
c = Classroom("Room 101", 35)
print(c.name, c.empty_desks, c.fill_rate)
c.seat(20)
print(c.occupied_desks, c.fill_rate)
c.dismiss(8)
print(c.empty_desks)
try:
c.seat(25)
except ValueError as e:
print(e)
try:
c.name = "X"
except AttributeError:
print("Cannot change classroom name")
Expected Output
Room 101 35 0.0
20 57.1
23
Not enough empty desks
Cannot change classroom name
Variant 10: Bike Station
A city bike-sharing system needs a BikeStation class. Each station has a name, total docks, and rented bikes.
nameis read-only (protected attribute, getter only).total_docksmust be at least1("Total docks must be at least 1"). Use a property; route initial value through the setter.rented_bikes(default0) cannot be negative ("Rented bikes cannot be negative") and cannot exceedtotal_docks("Rented bikes cannot exceed total docks"). Use a property; route initial value through the setter.- Read-only computed property
available_bikesreturnstotal_docks - rented_bikes. - Read-only computed property
rental_ratereturns the rental percentage as a float rounded to one decimal place. - Method
rent(bikes)increases rented bikes. Must be positive ("Number of bikes must be positive") and not exceed available bikes ("Not enough available bikes"). - Method
dock(bikes)decreases rented bikes. Must be positive ("Number of bikes must be positive") and not exceed rented bikes ("Cannot dock more than rented").
Input
s = BikeStation("Central Park", 25)
print(s.name, s.available_bikes, s.rental_rate)
s.rent(15)
print(s.rented_bikes, s.rental_rate)
s.dock(5)
print(s.available_bikes)
try:
s.rent(20)
except ValueError as e:
print(e)
try:
s.name = "X"
except AttributeError:
print("Cannot change station name")
Expected Output
Central Park 25 0.0
15 60.0
15
Not enough available bikes
Cannot change station name
Variant 11: Flight
An airline system needs a Flight class. Each flight has a flight number, total seats, and booked seats.
flight_numberis read-only (protected attribute, getter only).total_seatsmust be at least1("Total seats must be at least 1"). Use a property; route initial value through the setter.booked_seats(default0) cannot be negative ("Booked seats cannot be negative") and cannot exceedtotal_seats("Booked seats cannot exceed total seats"). Use a property; route initial value through the setter.- Read-only computed property
open_seatsreturnstotal_seats - booked_seats. - Read-only computed property
booking_ratereturns the booking percentage as a float rounded to one decimal place. - Method
book(tickets)increases booked seats. Must be positive ("Number of tickets must be positive") and not exceed open seats ("Not enough open seats"). - Method
cancel(tickets)decreases booked seats. Must be positive ("Number of tickets must be positive") and not exceed booked seats ("Cannot cancel more than booked").
Input
f = Flight("UZ-101", 180)
print(f.flight_number, f.open_seats, f.booking_rate)
f.book(120)
print(f.booked_seats, f.booking_rate)
f.cancel(30)
print(f.open_seats)
try:
f.book(100)
except ValueError as e:
print(e)
try:
f.flight_number = "X"
except AttributeError:
print("Cannot change flight number")
Expected Output
UZ-101 180 0.0
120 66.7
90
Not enough open seats
Cannot change flight number
Variant 12: Cinema Screen
A cinema needs a CinemaScreen class. Each screen has a name, total chairs, and taken chairs.
nameis read-only (protected attribute, getter only).total_chairsmust be at least1("Total chairs must be at least 1"). Use a property; route initial value through the setter.taken_chairs(default0) cannot be negative ("Taken chairs cannot be negative") and cannot exceedtotal_chairs("Taken chairs cannot exceed total chairs"). Use a property; route initial value through the setter.- Read-only computed property
open_chairsreturnstotal_chairs - taken_chairs. - Read-only computed property
fill_ratereturns the fill percentage as a float rounded to one decimal place. - Method
sell(tickets)increases taken chairs. Must be positive ("Number of tickets must be positive") and not exceed open chairs ("Not enough open chairs"). - Method
refund(tickets)decreases taken chairs. Must be positive ("Number of tickets must be positive") and not exceed taken chairs ("Cannot refund more than sold").
Input
s = CinemaScreen("Screen 1", 120)
print(s.name, s.open_chairs, s.fill_rate)
s.sell(80)
print(s.taken_chairs, s.fill_rate)
s.refund(20)
print(s.open_chairs)
try:
s.sell(70)
except ValueError as e:
print(e)
try:
s.name = "X"
except AttributeError:
print("Cannot change screen name")
Expected Output
Screen 1 120 0.0
80 66.7
60
Not enough open chairs
Cannot change screen name
This content will be available starting February 20, 2026.