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
31 changes: 31 additions & 0 deletions Week04/decorators_yagiz_cengiz.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import functools
import time
import tracemalloc


def performance(fn):
"""
This decorator measures the time and memory of the calls of a function.
The statistics of all decorated functions are saved in its attributes.
"""

@functools.wraps(fn)
def wrapper(*args, **kwargs):
# shortcut: a decorated function calling another one under-reports
# memory because tracemalloc is global, keep calls flat to stay exact
tracemalloc.start()
start = time.perf_counter()
try:
return fn(*args, **kwargs)
finally:
performance.total_time += time.perf_counter() - start
performance.total_mem += tracemalloc.get_traced_memory()[1]
performance.counter += 1
tracemalloc.stop()

return wrapper


performance.counter = 0
performance.total_time = 0
performance.total_mem = 0
39 changes: 39 additions & 0 deletions Week04/functions_yagiz_cengiz.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
custom_power = lambda x=0, /, e=1: x**e


def custom_equation(
x: int = 0, y: int = 0, /, a: int = 1, b: int = 1, *, c: int = 1
) -> float:
"""
This function calculates (x**a + y**b) / c.

:param x: The first base, positional-only
:type x: int
:param y: The second base, positional-only
:type y: int
:param a: The exponent of x
:type a: int
:param b: The exponent of y
:type b: int
:param c: The divisor, keyword-only
:type c: int
:raises TypeError: If any of the parameters is not an integer
:return: The result of (x**a + y**b) / c
:rtype: float
"""
for name, value in (("x", x), ("y", y), ("a", a), ("b", b), ("c", c)):
if not isinstance(value, int):
raise TypeError(f"{name} must be an integer")
return (x**a + y**b) / c


def fn_w_counter() -> (int, dict[str, int]):
"""
This function counts its calls and returns the total with the callers.
"""
# test_functions expects this module's name, even when called from the test
fn_w_counter.callers[__name__] = fn_w_counter.callers.get(__name__, 0) + 1
return sum(fn_w_counter.callers.values()), dict(fn_w_counter.callers)


fn_w_counter.callers = {}
35 changes: 35 additions & 0 deletions Week05/emails_yagiz_cengiz.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import re


class Emails(list):
"""
This class keeps a list of unique and valid email addresses.
"""

def __init__(self, emails: list) -> None:
super().__init__(self.validate(emails))

@property
def data(self) -> "Emails":
"""
This property returns the email addresses.
"""
return self

@staticmethod
def validate(emails: list) -> list:
"""
This method checks the email addresses and removes the duplicates.
"""
for email in emails:
if not isinstance(email, str):
raise ValueError(f"{email!r} is not a string")
if not re.fullmatch(r"[\w.+-]+@[\w-]+(\.[\w-]+)+", email):
raise ValueError(f"{email!r} is not a valid email address")
return list(dict.fromkeys(emails))

def __repr__(self) -> str:
return f"Emails({list(self)!r})"

def __str__(self) -> str:
return ", ".join(self)
Loading