added tut01

This commit is contained in:
Nils Pukropp
2024-10-17 16:09:29 +02:00
parent 5006902cc5
commit c1f4948cc8
80 changed files with 264 additions and 5418 deletions

View File

@ -1,153 +0,0 @@
---
marp: true
paginate: true
# class: invert
theme: rose-pine
footer: Tutorium 14 - 02.02.2024 - Nils Pukropp - https://s.narl.io/s/tutorium-14
header:
math: mathjax
---
# Tutorium 14 - 02.02.2024
Decorator, Testing
---
# Decorator
- **Design-Pattern**, oft auch **Wrapper** genannt
- Verpackt ein Objekt um **zusätzliche Funktionalität** zu bieten
- Funktionen sind auch Objekte
- eine Klasse ist ein Objekt
- Oft einfach **syntax sugar**
---
## Beispiel - execute_two_times
```python
def execute_two_times(fn: Callable[..., Any]) -> Callable[..., Any]:
def wrapper(*args, **kwargs)
fn(*args, **kwargs)
fn(*args, **kwargs)
return wrapper
return wrapper
@execute_two_times()
def print_two_times(msg: str):
print(msg)
print_two_times("hello") # hello
# hello
```
---
## Beispiel - execute_by
```python
def execute_by(n: int):
def wrapper(fn):
def wrapped_fn(*args, **kwargs):
for _ in range(0, n):
fn(*args, **kwargs)
return wrapped_fn
return wrapped_fn
return wrapper
@execute_by(10)
def print_ten_times(msg: str):
print(msg)
print_ten_times("hello") # hello
# hello
# ... (10 mal)
```
---
## Beispiel - CommandExecutor
```python
class CommandExecutor[R]:
def __init__(self):
self.__commands: dict[str, Callable[..., R]] = {}
```
---
## Beispiel - run
```python
def run(self, name: str, *args, **kwargs) -> list[R]:
results : list[R] = []
for command_name, command in self.__commands.items():
if command_name == name:
results += [command(*args, **kwargs)]
return results
```
---
## Beispiel - register
```python
def register(self, cmd: Callable[..., R]) -> Callable[..., R]:
self.__commands[cmd.__name__] = cmd
return cmd
```
---
## Beispiel - CommandExecutor
```python
class CommandExecutor[R]:
def __init__(self):
self.__commands: dict[str, Callable[..., R]] = {}
def run(self, name: str, *args, **kwargs) -> list[R]:
results : list[R] = []
for command_name, command in self.__commands.items():
if command_name == name:
results += [command(*args, **kwargs)]
return results
def register(self, cmd: Callable[..., R]) -> Callable[..., R]:
self.__commands[cmd.__name__] = cmd
return cmd
```
---
## Beispiel - How to use
```python
app = CommandExecutor[str]()
@app.register
def hello_world() -> str:
return 'hello_world'
@app.register
def divide(a: int, b: int) -> str:
if b == 0:
return "tried to divide by zero"
return str(a / b)
print(app.run('hello_world'))
print(app.run('divide', 5, 0))
print(app.run('divide', 10, 2))
```
---
## Decorator in der Klausur
- Waren noch nie Bestandteil der Klausur
- Mut zur Lücke
- Kann euch natürlich nichts versprechen
---
# Testen mit `pytest`

Binary file not shown.

View File

@ -1,36 +0,0 @@
from typing import Callable, Iterator
class CommandExecutor[R]:
def __init__(self):
self.__commands: dict[str, Callable[..., R]] = {}
def run(self, name: str, *args, **kwargs) -> list[R]:
results : list[R] = []
for command_name, command in self.__commands.items():
if command_name == name:
results += [command(*args, **kwargs)]
return results
def register(self, cmd: Callable[..., R]) -> Callable[..., R]:
self.__commands[cmd.__name__] = cmd
return cmd
if __name__ == '__main__':
app = CommandExecutor[str]()
@app.register
def hello_world() -> str:
return 'hello_world'
@app.register
def divide(a: int, b: int) -> str:
if b == 0:
return "tried to divide by zero"
return str(a / b)
print(app.run('hello_world'))
print(app.run('divide', 5, 0))
print(app.run('divide', 10, 2))

View File

@ -1,67 +0,0 @@
from typing import Any, Callable
def count_calls[T](func: Callable[..., T]) -> Callable[..., T]:
count_calls.calls = 0
def wrapper(*args, **kwargs) -> T:
init_calls = count_calls.calls
count_calls.calls += 1
result = func(*args, **kwargs)
wrapper.calls = count_calls.calls - init_calls
return result
return wrapper
def f(x: int, y: int) -> int:
if x % 2 == 0:
return x // 2
else:
return x + 2 * y - 1
def count_iterations(a: int, b: int) -> int:
f_a(a, a, b)
return f_a.calls - 1
@count_calls
def f_a(init: int, a: int, b: int) -> None:
if a < b:
return
return f_a(init, f(a, init), b)
def execute_by(n: int):
def wrapper(fn):
def wrapped_fn(*args, **kwargs):
for _ in range(0, n):
fn(*args, **kwargs)
return wrapped_fn
return wrapped_fn
return wrapper
@execute_by(10)
def hello_world():
print('hello world!')
@execute_by(10)
def print_ten_times(msg: str):
print(msg)
def execute_two_times(fn) -> Callable[..., Any]:
def wrapper(*args, **kwargs):
for _ in range(0, 2):
fn(*args, **kwargs)
return wrapper
return wrapper
@execute_two_times
def test(msg: str):
print(msg)
if __name__ == '__main__':
assert (i := count_iterations(7, 6)) == 3, i
assert (i := count_iterations(3, 2)) == 4, i
assert (i := count_iterations(13, 9)) == 18, i
assert (i := count_iterations(13, 10)) == 8, i
assert (i := count_iterations(3, 4)) == 0, i
print_ten_times("hello world")
test("hello")