--- 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`