diff --git a/prep_exercises/exercise1.py b/prep_exercises/exercise1.py new file mode 100644 index 0000000..af99eef --- /dev/null +++ b/prep_exercises/exercise1.py @@ -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 diff --git a/prep_exercises/exercise2typeannotation.py b/prep_exercises/exercise2typeannotation.py new file mode 100644 index 0000000..31d70e4 --- /dev/null +++ b/prep_exercises/exercise2typeannotation.py @@ -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}") diff --git a/prep_exercises/exercise3.py b/prep_exercises/exercise3.py new file mode 100644 index 0000000..7c2ac59 --- /dev/null +++ b/prep_exercises/exercise3.py @@ -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 \ No newline at end of file diff --git a/prep_exercises/exercise4.py b/prep_exercises/exercise4.py new file mode 100644 index 0000000..ac73881 --- /dev/null +++ b/prep_exercises/exercise4.py @@ -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()) diff --git a/prep_exercises/exercise5.py b/prep_exercises/exercise5.py new file mode 100644 index 0000000..ec692d8 --- /dev/null +++ b/prep_exercises/exercise5.py @@ -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()) diff --git a/prep_exercises/exercise6.py b/prep_exercises/exercise6.py new file mode 100644 index 0000000..8ca96da --- /dev/null +++ b/prep_exercises/exercise6.py @@ -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) \ No newline at end of file diff --git a/prep_exercises/exercise7.py b/prep_exercises/exercise7.py new file mode 100644 index 0000000..511a90d --- /dev/null +++ b/prep_exercises/exercise7.py @@ -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 \ No newline at end of file diff --git a/prep_exercises/exercise8laptopallocation.py b/prep_exercises/exercise8laptopallocation.py new file mode 100644 index 0000000..ca5dfd6 --- /dev/null +++ b/prep_exercises/exercise8laptopallocation.py @@ -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.") diff --git a/prep_exercises/exercise9inheritance.py b/prep_exercises/exercise9inheritance.py new file mode 100644 index 0000000..8d8866d --- /dev/null +++ b/prep_exercises/exercise9inheritance.py @@ -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 +# print(person2.get_full_name()) +#AttributeError: 'Parent' object has no attribute 'get_full_name' \ No newline at end of file