-
-
Notifications
You must be signed in to change notification settings - Fork 42
Sheffield | 25-SDC-Nov | Hassan Osman | Sprint 5 | Prep Exercises #293
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
base: main
Are you sure you want to change the base?
Changes from all commits
d7860a4
c6edd33
bbca608
597f47e
adec5ea
c202adf
4917fe7
ab0e5d5
b0143fd
5c7d52c
6803aed
dd86ef8
9df4222
bf4f92c
0b58dee
e133ed6
0692d80
93e8215
eaa2fa4
b7f3ae2
530b650
b55e70c
ccce3db
bb87b72
ce70769
a70ac33
550f320
ee4aae2
dc9fa85
23cf5c5
a6564a3
9485080
b86a9a4
dec7dc1
6306f1a
ddaf3fc
421d9b1
ecacbcd
0a0fc91
a7955e3
079a209
64fa3d7
0621a7a
c86cb07
6e8289f
e67ecc2
37a29f0
0e15f42
8e1c160
dbe6de6
315c87a
a790f41
5082b38
e25ff74
8bc0681
d4ab965
7a430c1
68993f5
d276be9
70bc59a
1eae1bb
45a6b7c
665b5d3
27fb6c5
9cfc190
017bce3
0cac4f2
6b1fc1e
da93203
12c6e38
3022a19
e981618
2702dd9
b0de1ee
f073259
1a0f28f
4a3d056
b1e5f1d
eb1be83
6c155a8
b469b8d
5c05376
6cf094f
60782dd
275feb8
5c49864
8cd2513
25307d4
43db6cf
ff5238e
40d209b
793653a
be69676
eec6b69
750d9b2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| .venv | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| #Write a Person class using @datatype which uses a datetime.date for date of birth, rather than an | ||
| #int for age. | ||
|
|
||
| #Re-add the is_adult method to it. | ||
|
|
||
|
|
||
| from datetime import date | ||
| from dataclasses import dataclass | ||
|
|
||
| @dataclass | ||
| class Person: | ||
| name: str | ||
| date_of_birth: date | ||
| preferred_operating_system: str | ||
|
|
||
| def is_adult(self) ->bool: | ||
| age_in_days = (date.today() - self.date_of_birth).days | ||
| age_in_years = age_in_days / 365.2425 | ||
| return age_in_years >= 18 | ||
|
|
||
|
|
||
|
|
||
| imran = Person("Imran", date(2003,12, 3), "Ubuntu") | ||
| print(imran.is_adult()) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| #Write a program which: | ||
|
|
||
| #1.Already has a list of Laptops that a library has to lend out. | ||
| #2.Accepts user input to create a new Person - it should use the input function to read a person’s | ||
| #name, age, and preferred operating system. | ||
| #3.Tells the user how many laptops the library has that have that operating system. | ||
| #4.If there is an operating system that has more laptops available, tells the user that if they’re willing to | ||
| #accept that operating system they’re more likely to get a laptop. | ||
|
|
||
| #You should convert the age and preferred operating system input from the user into more constrained | ||
| #types as quickly as possible, and should output errors to stderr and terminate the program with a non- | ||
| #zero exit code if the user input bad values. | ||
|
|
||
| from dataclasses import dataclass | ||
| import sys | ||
| from enum import Enum | ||
|
|
||
| class operatingSystem(Enum): | ||
| CHROMEOS = "ChromeOS" | ||
| WINDOWS = "Windows" | ||
| MACOS = "macOS" | ||
| LINUX = "Linux" | ||
| ARCH = "Arch Linux" | ||
| UBUNTU = "Ubuntu" | ||
|
|
||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class Person: | ||
| name: str | ||
| age: int | ||
| preferred_operating_system: str | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class Laptop: | ||
| id: int | ||
| manufacturer: str | ||
| model: str | ||
| screen_size_in_inches: float | ||
| operating_system: operatingSystem | ||
|
|
||
|
|
||
|
|
||
| laptops = [ | ||
| Laptop(id=1, manufacturer="HP", model="Chromebook Plus 514", screen_size_in_inches=14, operating_system=operatingSystem.CHROMEOS), | ||
| Laptop(id=2, manufacturer="Microsoft", model="XPS", screen_size_in_inches=13.8, operating_system=operatingSystem.WINDOWS), | ||
| Laptop(id=3, manufacturer="Apple", model="MacBook Air", screen_size_in_inches=15, operating_system=operatingSystem.MACOS), | ||
| Laptop(id=4, manufacturer="Lenovo", model="ThinkPad X220", screen_size_in_inches=12.5, operating_system=operatingSystem.LINUX), | ||
| Laptop(id=5, manufacturer="Dell", model="XPS", screen_size_in_inches=13.7, operating_system=operatingSystem.ARCH), | ||
| Laptop(id=6, manufacturer="Dell", model="XPS", screen_size_in_inches=10.4, operating_system=operatingSystem.ARCH), | ||
| Laptop(id=7, manufacturer="Dell", model="XPS", screen_size_in_inches=15.5, operating_system=operatingSystem.UBUNTU), | ||
| Laptop(id=8, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system=operatingSystem.UBUNTU), | ||
| Laptop(id=9, manufacturer="Apple", model="MacBook", screen_size_in_inches=13.3, operating_system=operatingSystem.MACOS), | ||
| ] | ||
|
|
||
|
|
||
| name_input = input("Enter your name: ") | ||
| if not name_input.isalpha(): | ||
| print("Name must contain letters only!") | ||
| sys.exit(1) | ||
|
|
||
| try: | ||
| age_input = int(input("Enter your age: ")) | ||
| except ValueError: | ||
| print("Enter a numeric value for the age!") | ||
| sys.exit(1) | ||
|
|
||
|
|
||
| def parse_os_input(user_input: str) -> operatingSystem: | ||
| clean = user_input.lower().replace(" ", "") | ||
|
|
||
| for os in operatingSystem: | ||
| if os.value.lower().replace(" ", "") == clean: | ||
| return os | ||
| print("Invalid operating system!", file=sys.stderr) | ||
| sys.exit(1) | ||
|
|
||
| options = ", ".join(os.value for os in operatingSystem) | ||
| preferred_operating_system_input = parse_os_input(input(f"Enter your preferred operating system (Select from: {options}) ")) | ||
|
|
||
|
|
||
|
|
||
| def person_builder(name_input: str, age_input:int, preferred_operating_system_input:str) ->Person: | ||
|
|
||
| return Person(name_input, age_input, preferred_operating_system_input) | ||
|
|
||
|
|
||
|
|
||
| def laptops_counter(preferred_operating_system_input:str) ->int: | ||
| sum = 0 | ||
| for laptop in laptops: | ||
| if preferred_operating_system_input == laptop.operating_system: | ||
| sum += 1 | ||
| user_os = preferred_operating_system_input.value | ||
| if sum == 1: | ||
| return f"There is {sum} laptop with {user_os} operating system" | ||
| elif sum > 1: | ||
| return f"There are {sum} laptops with {user_os} operating system" | ||
|
|
||
| print(laptops_counter(preferred_operating_system_input)) | ||
|
|
||
|
|
||
| user_os = preferred_operating_system_input | ||
|
|
||
| def more_available_os(user_os: operatingSystem): | ||
|
|
||
| os_counter = {} | ||
| for laptop in laptops: | ||
| os_counter[laptop.operating_system] = os_counter.get(laptop.operating_system, 0) + 1 | ||
|
|
||
| max_count = max(os_counter.values()) | ||
|
|
||
| user_os_count = os_counter.get(user_os, 0) | ||
|
|
||
| if user_os_count < max_count: | ||
| most_available_os = max(os_counter, key=os_counter.get) | ||
| print(f"If you’re open to using {most_available_os.value} operating system, you’ll have a better chance of getting a laptop.”") | ||
|
|
||
|
|
||
| more_available_os(preferred_operating_system_input) | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| # Add the is_adult code to the file you saved earlier. | ||
|
|
||
| # Run it through mypy - notice that no errors are reported - mypy | ||
| # understands that Person has a property named age so is happy | ||
| # with the function. | ||
|
|
||
| # 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. | ||
|
|
||
|
|
||
| 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) | ||
|
|
||
|
|
||
| def is_adult(person: Person) -> bool: | ||
| return person.age >= 18 | ||
|
|
||
| print(is_adult(imran)) | ||
|
|
||
|
|
||
|
|
||
| # New function: "is_engineer" takes "Person" as a parameter and tries to access "profession" - a property that does not exist. | ||
| def is_engineer(person: Person) -> bool: | ||
| return person.profession == "Engineer" | ||
|
|
||
| print(is_engineer(eliza)) | ||
|
|
||
| # After running through mypy, 2 errors related to the new function were reported: | ||
| # 1) exercise_five.py:36: error: Returning Any from function declared to return "bool" [no-any-return] | ||
| # since person does not have "profession" as attribute and thus its type is unknown, thus this function could be returning any type. Hence the error above. | ||
| # 2) exercise_five.py:36: error: "Person" has no attribute "profession" [attr-defined] | ||
| # The error above simply stating that attribute "profession" does not exist in the class "Person" | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| 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) | ||
|
|
||
| # Save the above code to a file, and run it through mypy. | ||
|
|
||
| #Read the error, and make sure you understand what it’s telling you. | ||
|
|
||
| # The error message simply says that the class: Person does not have "address" as an attribute. | ||
| # Therefore, the instances of the class: Person can not inheret an attribute that does not exist. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| from dataclasses import dataclass | ||
| from typing import List | ||
|
|
||
| @dataclass(frozen=True) | ||
| class Person: | ||
| name: str | ||
| #Add "age" attribute | ||
| age: int | ||
| children: List["Person"] | ||
|
|
||
| #Add "age" field and thier respective values to "fatma" and "aisha" - instances of class "Person" | ||
| fatma = Person(name="Fatma", age=14, children=[]) | ||
| aisha = Person(name="Aisha",age=22, children=[]) | ||
|
|
||
| ##Add "age" field and its values to "imran" - instance of class "Person" | ||
| imran = Person(name="Imran", age=44, children=[fatma, aisha]) | ||
|
|
||
| def print_family_tree(person: Person) -> None: | ||
| print(person.name) | ||
| for child in person.children: | ||
| print(f"- {child.name} ({child.age})") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This correctly prints out this person's children. Do you think there is a way to make it print out the whole family tree? (hint: recursion)
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great work on this task so far. I was thinking about if, for example in that screenshot, if Aisha had a child as well (i.e. Imran's grandchild). Could you design the function in such a way that it could print that out as well? Recursion might help here. |
||
|
|
||
| print_family_tree(imran) | ||
|
|
||
|
|
||
| #Fix the above code so that it works. You must not change the print on line 17 - we do want to print the | ||
| #children’s ages. (Feel free to invent the ages of Imran’s children.) | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
|
|
||
| def double(value): | ||
| return value * 2 | ||
|
|
||
| print(double("22")) | ||
|
|
||
|
|
||
| # 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? | ||
|
|
||
| # Initial prediction was that a type coercion may take place and string "22" will convert to integer 22 and thus the function returns 44. | ||
| # After running the code, I now know that it did not do what i expected. It duplicated/repeated the string and returned 2222. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| #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. | ||
|
|
||
| #Update the is_adult method to act the same as before. | ||
|
|
||
| from datetime import date | ||
|
|
||
|
|
||
| class Person: | ||
| def __init__(self, name: str, date_of_birth: date, preferred_operating_system: str): | ||
| self.name = name | ||
| self.preferred_operating_system = preferred_operating_system | ||
| #Add "date_of_birth" attribute to the "Person" class | ||
| self.date_of_birth = date_of_birth | ||
|
|
||
| def is_adult(self) ->bool: | ||
| age_in_days = (date.today() - self.date_of_birth).days | ||
| age_in_years = age_in_days / 365.2425 | ||
| return age_in_years >= 18 | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
| imran = Person("Imran", date(2003,12, 3), "Ubuntu") | ||
| print(imran.is_adult()) | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| #Think of the advantages of using methods instead of free functions. Write them down in your notebook. | ||
|
|
||
| # Easy and direct to data and thus more efficient when working on them. | ||
| # it's more reusable since all instances of a class inheret those methods defined in it automatically. | ||
| # you'll be less prone to make mistakes when using methods as part of a class/isntance of it as opposed to a free function attempting to aceess the class data. | ||
| # code is more organised and readable when methods are part of a class as opposed to when they're just free functions. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| 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: | ||
| for item in person.preferred_operating_systems: | ||
| if laptop.operating_system == item: | ||
| possible_laptops.append(laptop) | ||
| return possible_laptops | ||
|
|
||
|
|
||
| people = [ | ||
| Person(name="Imran", age=22, preferred_operating_systems=["Ubuntu", "Arch Linux", "macOS"]), | ||
| Person(name="Eliza", age=34, preferred_operating_systems=["Arch Linux", "macOS", "Ubuntu"]), | ||
| ] | ||
|
|
||
| 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}") | ||
|
|
||
|
|
||
| #Try changing the type annotation of Person.preferred_operating_system from str to List[str]. | ||
|
|
||
| #Run mypy on the code. | ||
|
|
||
| #It tells us different places that our code is now wrong, because we’re passing values of the wrong type. | ||
|
|
||
| #We probably also want to rename our field - lists are plural. Rename the field to preferred_operating_systems. | ||
|
|
||
| #Run mypy again. | ||
|
|
||
| #Fix all of the places that mypy tells you need changing. Make sure the program works as you’d expect. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| #Do not run the following code. | ||
|
|
||
| #This code contains bugs related to types. They are bugs mypy can catch. | ||
|
|
||
| #Read this code to understand what it’s trying to do. Add type annotations to the method parameters and | ||
| #return types of this code. Run the code through mypy, and fix all of the bugs that show up. When you’re | ||
| #confident all of the type annotations are correct, and the bugs are fixed, run the code and check it works. | ||
|
|
||
| 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", 9) | ||
| open_account(balances, "Olya", 7) | ||
|
|
||
| total_pence = sum_balances(balances) | ||
| total_string = format_pence_as_string(total_pence) | ||
|
|
||
| print(f"The bank accounts total {total_string}") |

Uh oh!
There was an error while loading. Please reload this page.