From 95decf82f2f978e733093a21ffd11773c784d456 Mon Sep 17 00:00:00 2001 From: JanefrancessC Date: Thu, 2 Jul 2026 12:28:51 +0100 Subject: [PATCH] feat: implement prep-exercises for sprint 5 --- prep-exercises/check_with_mypy.py | 32 +++++++++++++ prep-exercises/double.py | 13 ++++++ prep-exercises/enums.py | 73 ++++++++++++++++++++++++++++++ prep-exercises/inheritance.py | 46 +++++++++++++++++++ prep-exercises/person_class.py | 22 +++++++++ prep-exercises/person_dataclass.py | 22 +++++++++ prep-exercises/person_generics.py | 21 +++++++++ prep-exercises/person_method.py | 20 ++++++++ prep-exercises/type_refactoring.py | 42 +++++++++++++++++ 9 files changed, 291 insertions(+) create mode 100644 prep-exercises/check_with_mypy.py create mode 100644 prep-exercises/double.py create mode 100644 prep-exercises/enums.py create mode 100644 prep-exercises/inheritance.py create mode 100644 prep-exercises/person_class.py create mode 100644 prep-exercises/person_dataclass.py create mode 100644 prep-exercises/person_generics.py create mode 100644 prep-exercises/person_method.py create mode 100644 prep-exercises/type_refactoring.py diff --git a/prep-exercises/check_with_mypy.py b/prep-exercises/check_with_mypy.py new file mode 100644 index 000000000..28290436c --- /dev/null +++ b/prep-exercises/check_with_mypy.py @@ -0,0 +1,32 @@ +from typing import Dict + +def open_account(balances: Dict[str, int], name: str, amount: int) -> None: + balances[name] = amount + +def sum_balances(accounts: Dict[str, int]) -> int: + total: int = 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 = int(total_pence / 100) + pence = total_pence % 100 + return f"£{pounds}.{pence:02d}" + +balances: Dict[str, int] = { + "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}") diff --git a/prep-exercises/double.py b/prep-exercises/double.py new file mode 100644 index 000000000..4ded6fc14 --- /dev/null +++ b/prep-exercises/double.py @@ -0,0 +1,13 @@ +def double(value): + return value * 2 + +# Prediction - Since a string was passed as parameter, it will concatenate twice rather than multiply the number. + +print(double("22")) + +def double_number(value): + return value * 3 +# The bug is multiplying by 3 rather than 2 as the function name implies. +# To fix this, simply return value * 2 + +print(double_number(10)) diff --git a/prep-exercises/enums.py b/prep-exercises/enums.py new file mode 100644 index 000000000..ecd251169 --- /dev/null +++ b/prep-exercises/enums.py @@ -0,0 +1,73 @@ +from dataclasses import dataclass +from enum import Enum +from typing import List + +class OperatingSystem(Enum): + MACOS = "macOS" + ARCH = "Arch Linux" + UBUNTU = "Ubuntu" + +@dataclass(frozen=True) +class Person: + name: str + age: int + preferred_operating_system: OperatingSystem + +@dataclass(frozen=True) +class Laptop: + id: int + manufacturer: str + model: str + screen_size_in_inches: float + operating_system: OperatingSystem + +laptops = [ + Laptop(id=1, manufacturer="Dell", model="XPS", screen_size_in_inches=13, operating_system=OperatingSystem.ARCH), + Laptop(id=2, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system=OperatingSystem.UBUNTU), + Laptop(id=3, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system=OperatingSystem.UBUNTU), + Laptop(id=4, manufacturer="Apple", model="macBook", screen_size_in_inches=13, operating_system=OperatingSystem.MACOS), +] + +def count_laptops(laptops: List[Laptop], operating_system: OperatingSystem) -> int: + count = 0 + for laptop in laptops: + if laptop.operating_system == operating_system: + count += 1 + return count + +def most_available_os(laptops: List[Laptop]) -> OperatingSystem: + best_os = OperatingSystem.UBUNTU + best_count = count_laptops(laptops, best_os) + + for os in OperatingSystem: + current_count = count_laptops(laptops, os) + if current_count > best_count: + best_count = current_count + best_os = os + + return best_os + +name = input("Enter your name: ") +age = int(input("Enter your age: ")) +os_input = input("Enter preferred OS (macOS, Arch Linux, Ubuntu): ") + +try: + preferred_os = OperatingSystem(os_input) +except ValueError: + print("Invalid operating system.") + exit() + +person = Person(name, age, preferred_os) + +available = count_laptops(laptops, person.preferred_operating_system) + +print( + f"\nThere are {available} {person.preferred_operating_system.value} laptop(s) available." +) + +best_os = most_available_os(laptops) + +if best_os != person.preferred_operating_system: + print( + f"If you're willing to accept {best_os.value}, you're more likely to get a laptop." + ) diff --git a/prep-exercises/inheritance.py b/prep-exercises/inheritance.py new file mode 100644 index 000000000..dc5e9b9e3 --- /dev/null +++ b/prep-exercises/inheritance.py @@ -0,0 +1,46 @@ +class Parent: + # Initialise the class + def __init__(self, first_name: str, last_name: str): + self.first_name = first_name + self.last_name = last_name + +# Gets first_name and last_name from Parent class + def get_name(self) -> str: + return f"{self.first_name} {self.last_name}" + + +class Child(Parent): + # setup Child class from the superclass Parent + # has a new field for previous last names + def __init__(self, first_name: str, last_name: str): + super().__init__(first_name, last_name) + self.previous_last_names = [] + +# changes the previous lastname to a new provided lastname and adds the prev lastname to a list + def change_last_name(self, last_name) -> None: + self.previous_last_names.append(self.last_name) + self.last_name = last_name + +# creates a suffix and appends to fullname if the prev lastname List is not empty + 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}" + +# creates an instance of Child class which inherits from Parent class +person1 = Child("Elizaveta", "Alekseeva") +print(person1.get_name()) # Elizaveta Alekseeva +print(person1.get_full_name()) # Elizaveta Alekseeva +# Changes the lastname to "Tyurina" and append Alekseeva to the previous_last_name List +person1.change_last_name("Tyurina") +print(person1.get_name()) # Elizaveta Tyurina +print(person1.get_full_name()) # Elizaveta Tyurina (née Alekseeva) + +# creates an instance of Parent class +person2 = Parent("Elizaveta", "Alekseeva") +print(person2.get_name()) # Elizaveta Alekseeva +print(person2.get_full_name()) # Error: Parent class does not have the get_full_name() method/attribute and program crashes +person2.change_last_name("Tyurina") # Error: Parent class does not have the change_last_name() method, program crash +print(person2.get_name()) # Elizaveta Alekseeva +print(person2.get_full_name()) # Error: Parent class does not have the get_full_name() method/attribute, program crash diff --git a/prep-exercises/person_class.py b/prep-exercises/person_class.py new file mode 100644 index 000000000..9cf621646 --- /dev/null +++ b/prep-exercises/person_class.py @@ -0,0 +1,22 @@ +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) - Person class has no address attribute, hence the error message in mypy on lines 9 and 13 + +eliza = Person("Eliza", 34, "Arch Linux") +print(eliza.name) +# print(eliza.address) - same as line 9 + +def is_adult(person: Person) -> bool: + return person.age >= 18 + +print(is_adult(imran)) + +# This function will generate an attribute error when mypy runs it, because gender is not an attribute of the class, Person. +def check_gender(person: Person) -> str: + return person.gender diff --git a/prep-exercises/person_dataclass.py b/prep-exercises/person_dataclass.py new file mode 100644 index 000000000..35f22248f --- /dev/null +++ b/prep-exercises/person_dataclass.py @@ -0,0 +1,22 @@ +from datetime import date +from dataclasses import dataclass + +@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): + age -= 1 + + return age >= 18 + +imran = Person("Imran", date(2000, 10, 11), "Ubuntu") +print(imran) +print(imran.is_adult()) diff --git a/prep-exercises/person_generics.py b/prep-exercises/person_generics.py new file mode 100644 index 000000000..2a40a84f6 --- /dev/null +++ b/prep-exercises/person_generics.py @@ -0,0 +1,21 @@ +from dataclasses import dataclass +from typing import List +# from datetime import date + +@dataclass(frozen=True) +class Person: + name: str + age: int + children: List["Person"] + +fatma = Person(name="Fatma", age=10, children=[]) +aisha = Person(name="Aisha", age=7, children=[]) + +imran = Person(name="Imran", age=38, 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) diff --git a/prep-exercises/person_method.py b/prep-exercises/person_method.py new file mode 100644 index 000000000..8a0cada74 --- /dev/null +++ b/prep-exercises/person_method.py @@ -0,0 +1,20 @@ +import datetime as dt + +class Person: + def __init__(self, name: str, dob: dt.date, preferred_operating_system: str): + self.name = name + self.dob = dob + self.preferred_operating_system = preferred_operating_system + + def is_adult(self) -> bool: + today = dt.date.today() + + age = today.year - self.dob.year + + if (today.month, today.day) < (self.dob.month, self.dob.day): + age -= 1 + + return age >= 18 + +imran = Person("Imran", dt.date(1998, 11, 13), "Ubuntu") +print(imran.is_adult()) diff --git a/prep-exercises/type_refactoring.py b/prep-exercises/type_refactoring.py new file mode 100644 index 000000000..bf340f8ff --- /dev/null +++ b/prep-exercises/type_refactoring.py @@ -0,0 +1,42 @@ +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]: + possible_laptops = [] + for laptop in laptops: + if laptop.operating_system == person.preferred_operating_systems[0]: + 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", "macOS"]), +] + +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}")