Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions Perp-exercises/Generics6.1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from dataclasses import dataclass


@dataclass(frozen=True)
class Person:
name: str
age: int
children: list["Person"]


fatma = Person(name="Fatma", age=22, children=[])
aisha = Person(name="Aisha", age=17, children=[])

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})")


print_family_tree(imran)
25 changes: 25 additions & 0 deletions Perp-exercises/class-exercise3.1.py
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):
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))


def is_student(person: Person) -> bool:
return person.student
27 changes: 27 additions & 0 deletions Perp-exercises/dataclase-5.1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from datetime import date
from dataclasses import dataclass


@dataclass(frozen=True)
class Person:

name: str
date_of_birth: date
preferred_operating_system: str

def age(self) -> int:
current: date = date.today()
age: int = current.year - self.date_of_birth.year
if (current.month, current.day) < (
self.date_of_birth.month,
self.date_of_birth.day,
):
age -= 1
return age

def is_adult(self) -> bool:
return self.age() >= 18


imran = Person("Imran", date(2022, 10, 16), "Ubuntu")
print(imran.is_adult())
125 changes: 125 additions & 0 deletions Perp-exercises/enum8.1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
from enum import Enum
from typing import List
from dataclasses import dataclass


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: int
operating_system: OperatingSystem


@dataclass(frozen=True)
class Person:
name: str
age: int
preferred_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 group_laptops_by_operating_system(
laptops: List[Laptop],
) -> dict[OperatingSystem, List[Laptop]]:
available_laptops: dict[OperatingSystem, List[Laptop]] = {
OperatingSystem.UBUNTU: [],
OperatingSystem.ARCH: [],
OperatingSystem.MACOS: [],
}
for laptop in laptops:
available_laptops[laptop.operating_system].append(laptop)

return available_laptops


def how_many_match(
person: Person, available_laptops: dict[OperatingSystem, List[Laptop]]
) -> int:
return len(available_laptops[person.preferred_operating_system])


def most_available_operating_system(
available_laptops: dict[OperatingSystem, List[Laptop]],
) -> OperatingSystem:
if not available_laptops:
raise ValueError("No operating systems available")
max_len: int = -1
most_available: OperatingSystem
for key, val in available_laptops.items():
if len(val) > max_len:
max_len = len(val)
most_available = key

return most_available


def main() -> None:
name: str = input("Name: ")
age: int = int(input("Age: "))

print("""choose an operating system:
1.Ubuntu
2,Arch Linux
3.macOs""")
choice: int = int(input("Enter Your choice: "))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any input validation here? What is the UX like if something goes wrong?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback. I added a loop to validate the user's input. If the user enters an invalid choice, the program displays a message telling them they must enter a number between 1 and 3, then keeps asking until they enter a valid option. I think this provides a better user experience than letting the program continue with invalid input.

os_map: dict[int, OperatingSystem] = {
1: OperatingSystem.UBUNTU,
2: OperatingSystem.ARCH,
3: OperatingSystem.MACOS,
}

preferred_operating_system: OperatingSystem = os_map[choice]

person1: Person = Person(name, age, preferred_operating_system)

laptops_by_operating_system = group_laptops_by_operating_system(laptops)
matching_laptop_count: int = how_many_match(person1, laptops_by_operating_system)
print("We have", matching_laptop_count, "matches")
most_available_os: OperatingSystem = most_available_operating_system(
laptops_by_operating_system
)
if person1.preferred_operating_system != most_available_os:
print("Are you willing to accept ", most_available_os.value, "instead")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have a question like this, what is the user expected to do? Is there some way for them to answer the question / change the outcome of the program?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the feedback, You're right_ the original version asked the question and do not let the user to respond, so it couldn't affect the program's behaviour.

I have updated the code so the user can answer Y/N, If they accept the program will assigns them a laptop with the most available OS; otherwise, it keeps their original choice or exit if there is no suitable laptops is available



if __name__ == "__main__":
main()
6 changes: 6 additions & 0 deletions Perp-exercises/exercises1-1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# 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
# I predict that will return undefined or raise an error. However, it returned "2222"
# because double function repeats the string twice
Empty file added Perp-exercises/exercises1-2.py
Empty file.
59 changes: 59 additions & 0 deletions Perp-exercises/inheritance9.1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
class Parent: # Implement a class called Parent
def __init__(
self, first_name: str, last_name: str
): # Constructor that initializes the object's attributes.
self.first_name = first_name # Create the 'first_name' attribute and assign the constructor argument to it
self.last_name = last_name

def get_name(self) -> str: # Return the person's first name.
return f"{self.first_name} {self.last_name}"


class Child(Parent): # Implement a class called Child that inherit the class Parent
def __init__(
self, first_name: str, last_name: str
): # Constructor for derived class
super().__init__(
first_name, last_name
) # call the parent class to initialize inherited attributes.
self.previous_last_names = [] # Create a list to store Previous last names

def change_last_name(
self, last_name: str
) -> None: # implement a function that take one parameter (the new name)
self.previous_last_names.append(
self.last_name
) # and store the last name before setting a new value
self.last_name = last_name

def get_full_name(
self,
) -> (
str
): # declare a var and return full name with "nee "and fist name that assign when the object where declare
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"
) # declare an object of Child class and give two arguments as firstname and last name
print(person1.get_name()) # print full name (Elizaveta Alekseeva)
print(
person1.get_full_name()
) # print full name (Elizaveta Alekseeva) we did not change the last name yet
person1.change_last_name(
"Tyurina"
) # store the last name in pervious_last_name list then set a new value for last name "Tyurina"
print(person1.get_name()) # #print full name (Elizaveta Tyurina)
print(person1.get_full_name()) # print Elizaveta Tyurina (née Alekseeva)
person2 = Parent(
"Elizaveta", "Alekseeva"
) # declare an object of Parent class and give two arguments as firstname and last name
print(person2.get_name()) # print full name (Elizaveta Alekseeva)
# print(person2.get_full_name()) # Error: Parent does not define get_full_name().
# person2.change_last_name("Tyurina") ## Error: Parent does not define change_last_name().
print(person2.get_name()) # print full name (Elizaveta Alekseeva)
# print(person2.get_full_name()) # Error: Parent does not define get_full_name().
25 changes: 25 additions & 0 deletions Perp-exercises/method4.2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
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 age(self) -> int:
current: date = date.today()
age: int = current.year - self.date_of_birth.year
if (current.month, current.day) < (
self.date_of_birth.month,
self.date_of_birth.day,
):
age -= 1
return age

def is_adult(self) -> bool:
return self.age() >= 18


imran = Person("Imran", date(2022, 10, 16), "Ubuntu")
print(imran.is_adult())
5 changes: 5 additions & 0 deletions Perp-exercises/method_exercise4.1.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good explanations

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Think of the advantages of using methods instead of free functions. Write them down in your notebook.
# Polymorphism – Derived classes can override methods to provide different behavior.
# Encapsulation – Methods operate on the object's data (self), keeping data and behavior together.
# Inheritance – Methods are inherited by derived classes, reducing code duplication.
# Direct access to object state – Methods can access the object's attributes and other methods through self.
34 changes: 34 additions & 0 deletions Perp-exercises/mypy-exercise2.py
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: 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}")
Loading