generated from CodeYourFuture/Module-Template
-
-
Notifications
You must be signed in to change notification settings - Fork 21
London | July SDC | Ali Qassab | Sprint 4 | Prep exercises #44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
AliQassab
wants to merge
14
commits into
CodeYourFuture:main
Choose a base branch
from
AliQassab:prep-exercises
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
7f56176
add .gitignore
AliQassab dd0aa3b
Add why we use types exercise
AliQassab 350e595
Add mypy type checking exercise
AliQassab 3b72b37
Add classes and objects exercise
AliQassab 0ab20fb
Add methods exercise
AliQassab f422356
Add dataclasses exercise
AliQassab 76e3202
Add generics exercise
AliQassab 7c1f71d
Add type-guided refactorings exercise
AliQassab b169d9d
Add enums exercise
AliQassab 8b0db4c
Add inheritance exercise
AliQassab 5bb7641
Add requirements.txt
AliQassab 1f45822
Fix double_bug function to multiply by 2 instead of 3
AliQassab 099d936
Add an address parameter to the Person class __init__ and stored it a…
AliQassab 380df70
Replace hard-coded age with dynamic calculation from date_of_birth
AliQassab File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| # Virtual Environment | ||
| venv/ | ||
| env/ | ||
| ENV/ | ||
|
|
||
| # Python cache | ||
| __pycache__/ | ||
| *.pyc | ||
| *.pyo | ||
| *.pyd | ||
|
|
||
| # mypy cache | ||
| .mypy_cache/ | ||
|
|
||
| # IDE | ||
| .vscode/ | ||
| .idea/ | ||
| *.swp | ||
| *.swo | ||
|
|
||
| # OS | ||
| .DS_Store | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| class Person: | ||
| def __init__(self, name: str, age: int, preferred_operating_system: str, address: str): | ||
| self.name = name | ||
| self.age = age | ||
| self.preferred_operating_system = preferred_operating_system | ||
| self.address = address | ||
|
|
||
| def is_adult(self) -> bool: | ||
| return self.age >= 18 | ||
|
|
||
|
|
||
| imran = Person("Imran", 22, "Ubuntu", "123 Main St") | ||
| print(imran.name) | ||
| print(imran.address) | ||
| print(imran.is_adult()) | ||
|
|
||
| eliza = Person("Eliza", 34, "Arch Linux", "456 Oak Ave") | ||
| print(eliza.name) | ||
| print(eliza.address) | ||
|
|
||
|
|
||
| def get_address(person: Person) -> str: | ||
| return person.address | ||
|
|
||
| print(get_address(imran)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| 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: | ||
| current_date = date.today() | ||
| age = current_date.year - self.date_of_birth.year - ( | ||
| (current_date.month, current_date.day) < (self.date_of_birth.month, self.date_of_birth.day) | ||
| ) | ||
| return age >= 18 | ||
|
|
||
| # Example usage: | ||
| imran = Person("Imran", date(2001, 5, 15), "Ubuntu") | ||
| print(imran) | ||
| print(imran.is_adult()) | ||
|
|
||
| eliza = Person("Eliza", date(1990, 3, 20), "Arch Linux") | ||
| print(eliza) | ||
| print(eliza.is_adult()) | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| from dataclasses import dataclass | ||
| from enum import Enum | ||
|
|
||
| class OperatingSystem(Enum): | ||
| MACOS = "macOS" | ||
| UBUNTU = "Ubuntu" | ||
| ARCH = "Arch Linux" | ||
|
|
||
| @dataclass | ||
| class Laptop: | ||
| id: int | ||
| manufacturer: str | ||
| model: str | ||
| screen_size_in_inches: float | ||
| operating_system: OperatingSystem | ||
|
|
||
| laptops = [ | ||
| Laptop(id=1, manufacturer="Lenovo", model="ThinkPad", screen_size_in_inches=14, operating_system=OperatingSystem.ARCH), | ||
| Laptop(id=2, manufacturer="HP", model="Pavilion", screen_size_in_inches=15.6, operating_system=OperatingSystem.UBUNTU), | ||
| Laptop(id=3, manufacturer="Asus", model="ZenBook", screen_size_in_inches=13.3, operating_system=OperatingSystem.UBUNTU), | ||
| Laptop(id=4, manufacturer="Apple", model="MacBook Air", screen_size_in_inches=13, operating_system=OperatingSystem.MACOS), | ||
| ] | ||
|
|
||
| @dataclass | ||
| class Person: | ||
| name: str | ||
| age: int | ||
| preferred_operating_system: OperatingSystem | ||
|
|
||
|
|
||
| name = input('Please enter your name: ') | ||
|
|
||
| age_input = input('Please enter your age: ') | ||
| try: | ||
| age = int(age_input) | ||
| except ValueError: | ||
| print(f"Error: '{age_input}' is not a valid age. Please enter a number.") | ||
| exit() | ||
|
|
||
| preferred_os_input = input('Please enter your preferred operating system: ') | ||
| try: | ||
| preferred_operating_system = OperatingSystem(preferred_os_input) | ||
| except ValueError: | ||
| available_options = ', '.join([os.value for os in OperatingSystem]) | ||
| print(f"Error: '{preferred_os_input}' is not available. Please choose from: {available_options}") | ||
| exit() | ||
|
|
||
|
|
||
| person = Person(name=name, age=age, preferred_operating_system=preferred_operating_system) | ||
|
|
||
|
|
||
| number_of_available_laptops = sum( | ||
| 1 for laptop in laptops if laptop.operating_system == person.preferred_operating_system | ||
| ) | ||
|
|
||
| def offer_laptop_to_user() -> None: | ||
| offer = input('Would you like a laptop with this OS (yes / no) ? ') | ||
| if offer.lower() == "y" or offer.lower() == "yes": | ||
| print('Great! Please come on monday next week to collect your laptop') | ||
| else: | ||
| print('No problem. See you later.') | ||
|
|
||
| if number_of_available_laptops == 1: | ||
| print(f'There is {number_of_available_laptops} laptop available with your preferred operating system.') | ||
| offer_laptop_to_user() | ||
| elif number_of_available_laptops > 1: | ||
| print(f'There are {number_of_available_laptops} laptops available with your preferred operating system.') | ||
| offer_laptop_to_user() | ||
| else: | ||
| print('There are no laptops available with your preferred operating system.') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| from dataclasses import dataclass | ||
| from typing import List | ||
| from datetime import date | ||
|
|
||
| @dataclass(frozen=True) | ||
| class Person: | ||
| name: str | ||
| date_of_birth: date | ||
| children: List["Person"] | ||
|
|
||
| def age(self) -> int: | ||
| current_date = date.today() | ||
| age = current_date.year - self.date_of_birth.year - ( | ||
| (current_date.month, current_date.day) < (self.date_of_birth.month, self.date_of_birth.day) | ||
| ) | ||
| return age | ||
|
|
||
| # Calculate dates of birth based on current age | ||
| def years_ago(years: int) -> date: | ||
| today = date.today() | ||
| try: | ||
| return date(today.year - years, today.month, today.day) | ||
| except ValueError: # Handle leap year edge case (Feb 29) | ||
| return date(today.year - years, today.month, today.day - 1) | ||
|
|
||
| sara = Person(name="Sara", date_of_birth=years_ago(5), children=[]) | ||
| ahmed = Person(name="Ahmed", date_of_birth=years_ago(8), children=[]) | ||
|
|
||
| ali = Person(name="Ali", date_of_birth=years_ago(28), children=[sara]) | ||
| aya = Person(name="Aya", date_of_birth=years_ago(32), children=[ahmed]) | ||
|
|
||
| imran = Person(name="Imran", date_of_birth=years_ago(55), children=[ali, aya]) | ||
|
|
||
| def print_family_tree(person: Person) -> None: | ||
| print(f"{person.name} ({person.age()})") | ||
| for child in person.children: | ||
| print(f" - {child.name} ({child.age()})") | ||
| for grandchild in child.children: | ||
| print(f" - {grandchild.name} ({grandchild.age()})") | ||
|
|
||
| def count_family_members(person: Person) -> int: | ||
| count = 1 | ||
| for child in person.children: | ||
| count += count_family_members(child) | ||
| return count | ||
|
|
||
| print_family_tree(imran) | ||
| print(f"\nTotal family members: {count_family_members(imran)}") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| 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: list[str] = [] | ||
|
|
||
| def change_last_name(self, last_name: str) -> 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}" | ||
|
|
||
|
|
||
| print("Creating Child instance:") | ||
| person1 = Child("Sarah", "Johnson") | ||
| print(f"Name: {person1.get_name()}") | ||
| print(f"Full name: {person1.get_full_name()}") | ||
|
|
||
| print("\nChanging last name to Smith:") | ||
| person1.change_last_name("Smith") | ||
| print(f"Name: {person1.get_name()}") | ||
| print(f"Full name: {person1.get_full_name()}") | ||
|
|
||
| print("\nCreating Parent instance:") | ||
| person2 = Parent("Emma", "Wilson") | ||
| print(f"Name: {person2.get_name()}") | ||
|
|
||
| # person2.change_last_name("Brown") # Error: Parent doesn't have change_last_name method |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| from datetime import date | ||
|
|
||
| class Person: | ||
| def __init__(self, name: str, DoB: date, preferred_operating_system: str): | ||
| self.name = name | ||
| self.DoB = DoB | ||
| self.preferred_operating_system = preferred_operating_system | ||
|
|
||
| def is_adult(self) -> bool: | ||
| current_date = date.today() | ||
| age = current_date.year - self.DoB.year - ( | ||
| (current_date.month, current_date.day) < (self.DoB.month, self.DoB.day) | ||
| ) | ||
| return age >= 18 | ||
|
|
||
|
|
||
|
|
||
| eliza = Person("Eliza", date(2010, 5, 15), "Arch Linux") | ||
| print(f"{eliza.name} is adult: {eliza.is_adult()}") | ||
|
|
||
| sara = Person("Sara", date(1995, 12, 20), "macOS") | ||
| print(f"{sara.name} is adult: {sara.is_adult()}") | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| mypy==1.18.2 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| 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: dict[str, int] = { | ||
| "Sima": 700, | ||
| "Linn": 545, | ||
| "Georg": 831, | ||
| } | ||
|
|
||
| # Bugs fixed: | ||
| # 1. Added balances as first argument | ||
| # 2. Converted amounts to pence (int) | ||
| # 3. Fixed function name typo | ||
| 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}") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| from dataclasses import dataclass | ||
| from typing import Optional | ||
|
|
||
| # Before refactoring - unclear types | ||
| def process_user_data(data): | ||
| name = data[0] | ||
| age = data[1] | ||
| email = data[2] if len(data) > 2 else None | ||
|
|
||
| if age < 18: | ||
| return None | ||
|
|
||
| return f"{name} ({age}): {email or 'no email'}" | ||
|
|
||
|
|
||
| # After refactoring - clear types | ||
| @dataclass | ||
| class User: | ||
| name: str | ||
| age: int | ||
| email: Optional[str] = None | ||
|
|
||
| def is_adult(user: User) -> bool: | ||
| return user.age >= 18 | ||
|
|
||
| def format_user_info(user: User) -> str: | ||
| email_str = user.email if user.email else "no email" | ||
| return f"{user.name} ({user.age}): {email_str}" | ||
|
|
||
| def process_user(user: User) -> Optional[str]: | ||
| if not is_adult(user): | ||
| return None | ||
| return format_user_info(user) | ||
|
|
||
|
|
||
| # Testing old version | ||
| print(process_user_data(("Alice", 25, "alice@example.com"))) | ||
| print(process_user_data(("Bob", 16))) | ||
|
|
||
| # Testing new version | ||
| user1 = User("Alice", 25, "alice@example.com") | ||
| user2 = User("Bob", 16) | ||
|
|
||
| print(process_user(user1)) | ||
| print(process_user(user2)) | ||
|
|
||
|
|
||
| # Another example | ||
| def get_value(key: str, data: dict[str, int]) -> Optional[int]: | ||
| return data.get(key) | ||
|
|
||
| sample_data = {"a": 1, "b": 2} | ||
| result = get_value("a", sample_data) | ||
| if result is not None: | ||
| print(f"Found: {result}") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| def half(value): | ||
| return value / 2 | ||
|
|
||
| def double(value): | ||
| return value * 2 | ||
|
|
||
| def second(value): | ||
| return value[1] | ||
|
|
||
| # Prediction: double("22") will return "2222" because * operator repeats strings | ||
| print(double("22")) | ||
|
|
||
| # Testing other cases | ||
| print(half(22)) | ||
| # print(half("hello")) # This will error | ||
| # print(half("22")) # This will error | ||
|
|
||
| print(double(22)) | ||
| print(double("hello")) | ||
|
|
||
| # print(second(22)) # This will error | ||
| print(second("hello")) | ||
| print(second("22")) | ||
|
|
||
| def double_bug(number): | ||
| return number * 2 | ||
|
|
||
| print(double_bug(10)) # Returns 20 (correctly doubles the number) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is a benefit or drawback of writing the function this way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stores DoB (fixed), not age (changes over time), so is_adult() stays correct.
Rtores DoB (fixed), not age (changes over time), so is_adult() stays correct.