Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
24 changes: 24 additions & 0 deletions sprint5-prep-exercises/add_is_adult.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
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(person: Person) -> bool:
return person.age >= 18


def get_address(person: Person) -> str:
return person.address

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Does person have address in your data model?



imran = Person("Imran", 22, "Ubuntu")

print(imran.name)
print(is_adult(imran))
9 changes: 9 additions & 0 deletions sprint5-prep-exercises/advantagesOfMethods.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Better organisation — behaviour related to a class stays together with that class.

# Easier to discover — if I have a Person, I can look at the Person class to see what it can do.

# More readable — person.is_adult() clearly shows that is_adult is behaviour associated with a Person.

# Encapsulation — other code doesn't need to know the internal details of how Person calculates something.

# Easier maintenance/refactoring — if the internal representation changes, such as changing age to date_of_birth, we can update the method while callers can continue using person.is_adult().
16 changes: 16 additions & 0 deletions sprint5-prep-exercises/classesAndoObjects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
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)

#The error is that the code tries to access an attribute called address, but the Person class does not define an address attribute.
#Mypy knows that imran and eliza are Person objects, so it can detect that .address does not exist before we run the program.
19 changes: 19 additions & 0 deletions sprint5-prep-exercises/data_class.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
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):
today = date.today()
age = today.year - self.date_of_birth.year

return age >= 18


imran = Person("Imran", date(2000, 10, 10), "Ubuntu")
print(imran.is_adult())
109 changes: 109 additions & 0 deletions sprint5-prep-exercises/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
from dataclasses import dataclass
from enum import Enum
import sys


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


# 1. The library already has some laptops
laptops = [
Laptop(1, "Dell", "XPS", 13, OperatingSystem.ARCH),
Laptop(2, "Dell", "XPS", 15, OperatingSystem.UBUNTU),
Laptop(3, "Dell", "XPS", 15, OperatingSystem.UBUNTU),
Laptop(4, "Apple", "MacBook", 13, OperatingSystem.MACOS),
]


# 2. Get the person's name
name = input("Enter your name: ")


# Get age as text, then convert it to int immediately
age_input = input("Enter your age: ")

try:
age = int(age_input)
except ValueError:
print("Error: age must be a whole number.", file=sys.stderr)
sys.exit(1)


# Get operating system as text, then convert it to an enum immediately
os_input = input(
"Enter your preferred operating system "
"(Ubuntu, Arch Linux, macOS): "
)

try:
preferred_os = OperatingSystem(os_input)
except ValueError:
print(
"Error: operating system must be Ubuntu, Arch Linux, or macOS.",
file=sys.stderr,
)
sys.exit(1)


# Now we have correctly typed data, so create the Person
person = Person(
name=name,
age=age,
preferred_operating_system=preferred_os,
)


# 3. Count laptops with the person's preferred operating system
preferred_count = 0

for laptop in laptops:
if laptop.operating_system == person.preferred_operating_system:
preferred_count += 1


print(
f"The library has {preferred_count} laptop(s) "
f"with {person.preferred_operating_system.value}."
)


# 4. Check whether another operating system has more laptops
for operating_system in OperatingSystem:

# Don't compare their preferred OS with itself
if operating_system == person.preferred_operating_system:
continue

count = 0

for laptop in laptops:
if laptop.operating_system == operating_system:
count += 1

if count > preferred_count:
print(
f"If you are willing to use {operating_system.value}, "
f"you are more likely to get a laptop because "
f"the library has {count} available."
)


23 changes: 23 additions & 0 deletions sprint5-prep-exercises/generic.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


fatma = Person(name="Fatma", age= 26, children=[])
aisha = Person(name="Aisha", age = 20, children=[])

imran = Person(name="Imran", age = 45, 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)
67 changes: 67 additions & 0 deletions sprint5-prep-exercises/inheritance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
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: 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" (previously {self.previous_last_names[0]})"

return f"{self.first_name} {self.last_name}{suffix}"


person1 = Child("Sara", "Ali")

print(person1.get_name())
print(person1.get_full_name())

person1.change_last_name("Ahmed")

print(person1.get_name())
print(person1.get_full_name())


person2 = Parent("Sara", "Ali")

print(person2.get_name())

# These lines would cause errors because these methods
# only exist in Child, not Parent:

# print(person2.get_full_name())
# person2.change_last_name("Ahmed")

print(person2.get_name())

# This would also cause an error:
# print(person2.get_full_name())


# The important inheritance relationship is:

# Parent
# │
# ├── get_name()
# │
# ▼
# Child
# ├── inherits get_name()
# ├── adds change_last_name()
# └── adds get_full_name()

# So a Child can use the inherited Parent method, but a Parent cannot use methods that only exist in Child.
9 changes: 9 additions & 0 deletions sprint5-prep-exercises/limits_of_type_checking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Read the above code and write down what the bug is. How would you fix it?

def double(number):
# return number * 3
return number * 2 # I would fix it like this

print(double(10))

#Because double function is expected to double or multiply a number by two but in contrast it is multiplying by 3.
24 changes: 24 additions & 0 deletions sprint5-prep-exercises/methods.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
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):
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


imran = Person("Imran", date(2000, 2, 10), "Ubuntu")
print(imran.is_adult())
14 changes: 14 additions & 0 deletions sprint5-prep-exercises/predict_double.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# 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?
def half(value):
return value / 2

def double(value):
return value * 2

def second(value):
return value[1]

print(double(22))

#So I predicted the string would be doubled(repeated) --> "2222"
#As in Python, multiplying a string by an integer means repeat the string
38 changes: 38 additions & 0 deletions sprint5-prep-exercises/type_annotation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
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}")


Loading
Loading