Skip to content
Open
18 changes: 18 additions & 0 deletions prep_exercises/exercise1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
def double(value):
return value * 2

print(double("22"))
#Predict what double("22") will do

#Answer
#"2222" because "22" will be treated as a string and then the program just duplicates it and return 2222 with a string value

def double(number):
return number * 3

print(double(10))

#find the bug
#answer
#This is a logic error instead of giving the double it returns the triple of the number
#we can improve it by changing 3 by 2 since it doesnt have any type error
31 changes: 31 additions & 0 deletions prep_exercises/exercise2typeannotation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
def open_account(balances: dict[str, int], name: str, amount: int) -> None:
balances[name] = amount

def sum_balances(accounts: dict[str, int]) -> int:
total = 0
for name, pence in accounts.items():
print(f"{name} had balance {pence}")
total += pence
return total

def format_pence_as_string(total_pence: int) -> str:
if total_pence < 100:
return f"{total_pence}p"
pounds = total_pence // 100
pence = total_pence % 100
return f"£{pounds}.{pence:02d}"


balances = {
"Sima": 700,
"Linn": 545,
"Georg": 831,
}

open_account(balances, "Tobi", 913)
open_account(balances, "Olya", 713)

total_pence = sum_balances(balances)
total_string = format_pence_as_string(total_pence)

print(f"The bank accounts total {total_string}")
29 changes: 29 additions & 0 deletions prep_exercises/exercise3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class Person:
def __init__(self, name: str, age: int, preferred_operating_system: str):
self.name = name
self.age = age
self.preferred_operating_system = preferred_operating_system

imran = Person("Imran", 22, "Ubuntu")
print(imran.name)
print(imran.address)

eliza = Person("Eliza", 34, "Arch Linux")
print(eliza.name)
print(eliza.address)

#imran.address and eliza.address is not valid attribute
#error: "Person" has no attribute "address"


def is_adult(person: Person) -> bool:
return person.age >= 18

print(is_adult(imran))
#ok

def get_city(person: Person) -> str:
return person.city
#person has no attribute city.

#to run mypy mypy ./***.py
42 changes: 42 additions & 0 deletions prep_exercises/exercise4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
class Person:
def __init__(self, name: str, age: int, preferred_operating_system: str):
self.name = name
self.age = age
self.preferred_operating_system = preferred_operating_system

def is_adult(self):
return self.age >= 18

imran = Person("Imran", 22, "Ubuntu")
print(imran.is_adult())

#✍️exercise
#Think of the advantages of using methods instead of free functions. Write them down in your notebook.


#answer
#Reusability
#Polymorphism – Different subclasses can override the same method name with different behaviour.


#exercise
#Change the Person class to take a date of birth (using the standard library’s datetime.date class) and store it in a field instead of age.
from datetime import date
class Person:
def __init__(self, name: str, date_of_birth: date, preferred_operating_system: str):
self.name = name
self.date_of_birth = date_of_birth
self.preferred_operating_system = preferred_operating_system

def is_adult(self) -> bool:
today = date.today()
age = today.year - self.date_of_birth.year
if (today.month, today.day) < (self.date_of_birth.month, self.date_of_birth.day):
age -= 1
return age >= 18
#example
imra = Person("Imra", date(2003, 7, 14), "Ubuntu")
eliz = Person("Eliz", date(1991, 3, 25), "Arch Linux")

print(imra.is_adult())
print(eliz.is_adult())
22 changes: 22 additions & 0 deletions prep_exercises/exercise5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from dataclasses import dataclass
from datetime import date

@dataclass(frozen=True)
class Person:
name: str
date_of_birth: date
preferred_operating_system: str

def is_adult(self) -> bool:
today = date.today()
age = today.year - self.date_of_birth.year
if (today.month, today.day) < (self.date_of_birth.month, self.date_of_birth.day): #if bd havent occured even once this year -1
age -= 1
return age >= 18

#example
imran = Person("Imran", date(2003, 7, 14), "Ubuntu")
eliza = Person("Eliza", date(1991, 3, 25), "Arch Linux")
print(imran)
print(imran.is_adult())
print(eliza.is_adult())
22 changes: 22 additions & 0 deletions prep_exercises/exercise6.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from dataclasses import dataclass
from typing import List

@dataclass(frozen=True)
class Person:
name: str
age: int
children: List["Person"]

fatma = Person(name="Fatma", age=8, children=[])
aisha = Person(name="Aisha", age=6, children=[])

imran = Person(name="Imran", age=35, children=[fatma, aisha])


def print_family_tree(person: Person) -> None:
print(person.name)
for child in person.children:
print(f"- {child.name} ({child.age})")


print_family_tree(imran)
43 changes: 43 additions & 0 deletions prep_exercises/exercise7.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from dataclasses import dataclass
from typing import List
@dataclass(frozen=True)
class Person:
name: str
age: int
preferred_operating_systems: List[str]

@dataclass(frozen=True)
class Laptop:
id: int
manufacturer: str
model: str
screen_size_in_inches: float
operating_system: str


def find_possible_laptops(laptops: List[Laptop], person: Person) -> List[Laptop]:
# create a set of lowercase preferred names for faster membership checks
prefs_lower = {os.lower() for os in person.preferred_operating_systems} #turn the string in to lowercase and it stores is on our set called prefs_lower
possible_laptops: List[Laptop] = []
for laptop in laptops:
if laptop.operating_system.lower() in prefs_lower:
possible_laptops.append(laptop)
return possible_laptops

people = [
Person(name="Imran", age=22, preferred_operating_systems=["Ubuntu", "Arch Linux"]),
Person(name="Eliza", age=34, preferred_operating_systems=["Arch Linux"]),
]

laptops = [
Laptop(id=1, manufacturer="Dell", model="XPS", screen_size_in_inches=13, operating_system="Arch Linux"),
Laptop(id=2, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system="Ubuntu"),
Laptop(id=3, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system="ubuntu"),
Laptop(id=4, manufacturer="Apple", model="macBook", screen_size_in_inches=13, operating_system="macOS"),
]

for person in people:
possible_laptops = find_possible_laptops(laptops, person)
print(f"Possible laptops for {person.name}: {possible_laptops}")
# now ubuntu and Ubuntu is the same match
# by basically checking if the lower case version of our text is there we declare it is the same thing
61 changes: 61 additions & 0 deletions prep_exercises/exercise8laptopallocation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from dataclasses import dataclass
from enum import Enum
from typing import List
from collections import Counter
import sys

class OperatingSystem(Enum):
MACOS = "macOS"
ARCH = "Arch Linux"
UBUNTU = "Ubuntu"


@dataclass(frozen=True)
class Laptop:
id: int
manufacturer: str
model: str
screen_size_in_inches: float
operating_system: OperatingSystem

@dataclass(frozen=True)
class Person:
name: str
age: int
preferred_operating_system: OperatingSystem

#library’s laptops
laptops = [
Laptop(1, "Dell", "XPS 13", 13, OperatingSystem.ARCH),
Laptop(2, "Dell", "XPS 15", 15, OperatingSystem.UBUNTU),
Laptop(3, "Lenovo", "ThinkPad", 14, OperatingSystem.UBUNTU),
Laptop(4, "Apple", "MacBook Air", 13, OperatingSystem.MACOS),
]
#user input
name = input("Enter your name: ").strip()
try:
age = int(input("Enter your age: ").strip())
except ValueError:
print("Error Age must be a number ", file=sys.stderr)
sys.exit(1)
os_input = input("Enter your preferred operating system (macOS / Arch Linux / Ubuntu): ").strip()
try:
preferred_os = OperatingSystem(os_input)
except ValueError:
print(f"Error '{os_input}' is not a valid operating system.", file=sys.stderr)
print("Valid options are:", [os.value for os in OperatingSystem], file=sys.stderr)
sys.exit(1)

#Processing
person = Person(name=name, age=age, preferred_operating_system=preferred_os)
matching_laptops = [l for l in laptops if l.operating_system == person.preferred_operating_system]

print(f"\n library has {len(matching_laptops)} laptop/s with {preferred_os.value}")

#suggest an alternative if better availability
os_counts = Counter([l.operating_system for l in laptops])
most_common_os, most_common_count = os_counts.most_common(1)[0]

if most_common_os != preferred_os and most_common_count > len(matching_laptops):
print(f"💡 There are more laptops with {most_common_os.value}.")
print(f"If you’re willing to use {most_common_os.value}, you’re more likely to get one.")
49 changes: 49 additions & 0 deletions prep_exercises/exercise9inheritance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
class Parent:
def __init__(self, first_name: str, last_name: str):
self.first_name = first_name
self.last_name = last_name

def get_name(self) -> str:
return f"{self.first_name} {self.last_name}"


class Child(Parent):
def __init__(self, first_name: str, last_name: str):
super().__init__(first_name, last_name)
self.previous_last_names = []

def change_last_name(self, last_name) -> None:
self.previous_last_names.append(self.last_name)
self.last_name = last_name

def get_full_name(self) -> str:
suffix = ""
if len(self.previous_last_names) > 0:
suffix = f" (née {self.previous_last_names[0]})"
return f"{self.first_name} {self.last_name}{suffix}"

person1 = Child("Elizaveta", "Alekseeva")
print(person1.get_name())
print(person1.get_full_name())
person1.change_last_name("Tyurina")
print(person1.get_name())
print(person1.get_full_name())

person2 = Parent("Elizaveta", "Alekseeva")
print(person2.get_name())
#print(person2.get_full_name())
#person2.change_last_name("Tyurina")
print(person2.get_name())
#print(person2.get_full_name())


#without commenting the three lines the output was like thiss
#Elizaveta Alekseeva
#Elizaveta Alekseeva
#Elizaveta Tyurina
#Elizaveta Alekseeva
#Elizaveta Tyurina (née Alekseeva)
#Traceback (most recent call last):
# File "/Users/Module-Decomposition/prep_exercises/exercise9inheritance.py", line 34, in <module>
# print(person2.get_full_name())
#AttributeError: 'Parent' object has no attribute 'get_full_name'
Loading