Created
July 4, 2024 09:32
-
-
Save FMeinicke/f1ed71fc1e93436849eb52b9d03d9df0 to your computer and use it in GitHub Desktop.
Compilation of different methods to create function decorators with and without parameters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from __future__ import annotations | |
| from functools import wraps | |
| from typing import overload | |
| def func_decorator(func): | |
| @wraps(func) | |
| def wrapper(*args, **kwargs): | |
| print(f"func_decorator: Calling {func.__name__} with args: {args}, kwargs: {kwargs}") | |
| return func(*args, **kwargs) | |
| return wrapper | |
| def func_decorator_with_args(*dargs, **dkwargs): | |
| def decorator(func): | |
| @wraps(func) | |
| def wrapper(*args, **kwargs): | |
| print( | |
| f"func_decorator_with_args: Calling {func.__name__} with args: {args}, kwargs: {kwargs}, " | |
| f"decorator dargs: {dargs}, decorator dkwargs: {dkwargs}" | |
| ) | |
| return func(*args, **kwargs) | |
| return wrapper | |
| print(f"decorator dargs: {dargs}, decorator dkwargs: {dkwargs}") | |
| return decorator | |
| def test1(): | |
| @func_decorator | |
| def func(*args, **kwargs): | |
| print(f"func args: {args}, kwargs: {kwargs}") | |
| @func_decorator_with_args("darg1", "darg2", dkwarg1="dkwarg1", dkwarg2="dkwarg2") | |
| def func_with_args(*args, **kwargs): | |
| print(f"func_with_args args: {args}, kwargs: {kwargs}") | |
| print("---------------") | |
| func(1, 2, 3, kwarg1="kwarg1", kwarg2="kwarg2") | |
| func_with_args(1, 2, 3, kwarg1="kwarg1", kwarg2="kwarg2") | |
| @overload | |
| def func_decorator_with_and_without_args(func): ... | |
| @overload | |
| def func_decorator_with_and_without_args(*, dkwarg="default_kwarg"): ... | |
| def func_decorator_with_and_without_args(*dargs, dkwarg="default_kwarg"): | |
| def decorator(func): | |
| @wraps(func) | |
| def wrapper(*args, **kwargs): | |
| print( | |
| f"func_decorator_with_and_without_args: Calling {func.__name__} with args: {args}, kwargs: {kwargs}, " | |
| f"decorator dkwarg: {dkwarg}" | |
| ) | |
| return func(*args, **kwargs) | |
| return wrapper | |
| print(f"decorator dargs: {dargs}, decorator dkwarg: {dkwarg}") | |
| if len(dargs) > 1: | |
| raise ValueError("Only one positional argument is allowed (the function to decorate)") | |
| # see if we're being called as @decorator or @decorator() | |
| if len(dargs) == 0: | |
| # we're called with parentheses as @decorator(kwargs...) | |
| return decorator | |
| # we're called as @decorator without parentheses | |
| func = dargs[0] | |
| if not callable(func): | |
| raise TypeError("The function to decorate must be a callable") | |
| return decorator(func) | |
| def test2(): | |
| @func_decorator_with_and_without_args | |
| def func(*args, **kwargs): | |
| print(f"func args: {args}, kwargs: {kwargs}") | |
| @func_decorator_with_and_without_args(dkwarg="dkwarg") | |
| def func_with_args(*args, **kwargs): | |
| print(f"func_with_args args: {args}, kwargs: {kwargs}") | |
| try: | |
| @func_decorator_with_and_without_args() | |
| def func_with_empty_parens(*args, **kwargs): | |
| print(f"func_with_empty_parens args: {args}, kwargs: {kwargs}") | |
| except ValueError as e: | |
| print(f"func_with_empty_parens: {e}") | |
| try: | |
| @func_decorator_with_and_without_args("darg") | |
| def func_with_single_arg_invalid(*args, **kwargs): | |
| print(f"func_with_single_arg_invalid args: {args}, kwargs: {kwargs}") | |
| except TypeError as e: | |
| print(f"func_with_single_arg_invalid: {e}") | |
| try: | |
| @func_decorator_with_and_without_args("darg1", "darg2") | |
| def func_with_args_invalid(*args, **kwargs): | |
| print(f"func_with_args_invalid args: {args}, kwargs: {kwargs}") | |
| except ValueError as e: | |
| print(f"func_with_args_invalid: {e}") | |
| try: | |
| @func_decorator_with_and_without_args(dkwarg="dkwarg", dkwarg2="dkwarg2") | |
| def func_with_multiple_kwargs_invalid(*args, **kwargs): | |
| print(f"func_with_multiple_kwargs_invalid args: {args}, kwargs: {kwargs}") | |
| except TypeError as e: | |
| print(f"func_with_multiple_kwargs_invalid: {e}") | |
| print("---------------") | |
| func(1, 2, 3, kwarg1="kwarg1", kwarg2="kwarg2") | |
| func_with_args(1, 2, 3, kwarg1="kwarg1", kwarg2="kwarg2") | |
| test1() | |
| print("---------------") | |
| test2() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment