diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e6395c4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.venv +node_modules \ No newline at end of file diff --git a/bank_accounts.py b/bank_accounts.py new file mode 100644 index 0000000..b17ac2d --- /dev/null +++ b/bank_accounts.py @@ -0,0 +1,36 @@ +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 = 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 = { + "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/classes_and_objects.py b/classes_and_objects.py new file mode 100644 index 0000000..9b9289d --- /dev/null +++ b/classes_and_objects.py @@ -0,0 +1,33 @@ +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) address is not an attribute of the Person class + +eliza = Person("Eliza", 34, "Arch Linux") +print(eliza.name) +# print(eliza.address) + + +def is_adult(person: Person) -> bool: + return person.age >= 18 + + +print(is_adult(imran)) + + +# Exercise: +# Write a new function in the file that accepts a Person as a parameter and tries to access a property that +# doesn’t exist. Run it through mypy and check that it does report an error. + + +def live_in_london(person: Person) -> bool: + return person.address == "London" + + +live_in_london(imran) diff --git a/dataclass.py b/dataclass.py new file mode 100644 index 0000000..f72ad86 --- /dev/null +++ b/dataclass.py @@ -0,0 +1,26 @@ +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: + eighteen_birthday = date( + self.date_of_birth.year + 18, + self.date_of_birth.month, + self.date_of_birth.day, + ) + return date.today() >= eighteen_birthday + + +imran = Person("Imran", date(2019, 12, 22), "Ubuntu") +print(imran.is_adult()) + +imran2 = Person("Imran2", date(2000, 12, 22), "Ubuntu") +print(imran2.is_adult()) + +print(imran == imran2) diff --git a/double.py b/double.py new file mode 100644 index 0000000..06ff078 --- /dev/null +++ b/double.py @@ -0,0 +1,17 @@ +def half(value): + return value / 2 + + +def double(value): + return value * 2 + + +def second(value): + return value[1] + + +# ✍️exercise +# Predict what double("22") will do. Then run the code and check. Did it do what you expected? Why did it return the value it did + +# Answer +# double "22" will return "2222" because when we multiply string, code write that string several times diff --git a/enums.py b/enums.py new file mode 100644 index 0000000..78de424 --- /dev/null +++ b/enums.py @@ -0,0 +1,137 @@ +from dataclasses import dataclass +from typing import List, Tuple +from enum import Enum +import sys +from collections import Counter + + +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, + ), +] + + +users = [] + + +def find_possible_laptops(laptops: List[Laptop], person: Person) -> List[Laptop]: + possible_laptops = [] + for laptop in laptops: + if laptop.operating_system == person.preferred_operating_system: + possible_laptops.append(laptop) + return possible_laptops + + +def input_validation() -> Tuple[str, int, OperatingSystem]: + input_user_name = input("Enter your name: ") + if not isinstance(input_user_name, str): + sys.stderr.write("Name must be a string") + sys.exit(1) + + try: + input_user_age = int(input("Enter your age: ")) + except ValueError: + sys.stderr.write("Age must be an integer") + sys.exit(1) + + input_preferred_operating_system = input( + "Enter your preferred operating system (macOS/Arch Linux/Ubuntu): " + ) + + try: + preferred_os = OperatingSystem(input_preferred_operating_system) + except ValueError: + sys.stderr.write("Wrong OS") + sys.exit(1) + + return input_user_name, input_user_age, preferred_os + + +def count_operating_systems(laptops: List[Laptop]) -> Counter[OperatingSystem]: + return Counter(laptop.operating_system for laptop in laptops) + + +def recommend_os(user: Person, laptops: List[Laptop]) -> None: + os_counts = count_operating_systems(laptops) + most_common_os, most_common_count = os_counts.most_common(1)[0] + + user_count = os_counts[user.preferred_operating_system] + + if ( + most_common_os != user.preferred_operating_system + and user_count < most_common_count + ): + print(f"More laptops are available with {most_common_os.value}.") + + +def laptop() -> None: + input_user_name, input_user_age, input_preferred_operating_system = ( + input_validation() + ) + + users.append( + Person( + name=input_user_name, + age=input_user_age, + preferred_operating_system=OperatingSystem( + input_preferred_operating_system + ), + ), + ) + for user in users: + possible_laptops = find_possible_laptops(laptops, user) + print( + f"Possible laptops for {user.name}:\n{'\n'.join(map(str, possible_laptops))}", + ) + recommend_os(user, laptops) + + +laptop() diff --git a/generics.py b/generics.py new file mode 100644 index 0000000..de2e39c --- /dev/null +++ b/generics.py @@ -0,0 +1,24 @@ +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=5, children=[]) +aisha = Person(name="Aisha", age=20, children=[]) + +imran = Person(name="Imran", age=49, 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/inheritance.py b/inheritance.py new file mode 100644 index 0000000..b8db7ea --- /dev/null +++ b/inheritance.py @@ -0,0 +1,39 @@ +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()) +# Commented out these prints because the Parent class doesn't have these methods, which causes an "AttributeError" diff --git a/is_adult.py b/is_adult.py new file mode 100644 index 0000000..07c1f9c --- /dev/null +++ b/is_adult.py @@ -0,0 +1,20 @@ +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: + eighteen_birthday = date( + self.date_of_birth.year + 18, + self.date_of_birth.month, + self.date_of_birth.day, + ) + return date.today() >= eighteen_birthday + + +imran = Person("Imran", date(2019, 12, 22), "Ubuntu") +print(imran.is_adult()) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f0aa93a --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +mypy diff --git a/type_guided_refactorings.py b/type_guided_refactorings.py new file mode 100644 index 0000000..7645f71 --- /dev/null +++ b/type_guided_refactorings.py @@ -0,0 +1,67 @@ +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 in person.preferred_operating_systems: + possible_laptops.append(laptop) + return possible_laptops + + +people = [ + Person(name="Imran", age=22, preferred_operating_systems=["Ubuntu"]), + 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}")