11.10. Decorator Function

  • func is a reference to function which is being decorated

  • args arbitrary number of positional arguments

  • kwargs arbitrary number of keyword arguments

  • By calling func(*args, **kwargs) you actually run original (wrapped) function with it's original arguments

Definition:

>>> def mydecorator(func):
...     def wrapper(*args, **kwargs):
...         return func(*args, **kwargs)
...     return wrapper

Usage:

>>> @mydecorator
... def say_hello():
...     return 'hello'
>>>
>>>
>>> say_hello()
'hello'

11.10.1. Assignments

Code 11.25. Solution
"""
* Assignment: Decorator Syntax About
* Complexity: easy
* Lines of code: 5 lines
* Time: 3 min

English:
    1. Create decorator `mydecorator`
    2. Decorator should have `wrapper` with `*args` and `**kwargs` parameters
    3. Wrapper should call original function with it's original parameters,
       and return its value
    4. Decorator should return `wrapper` function
    5. Run doctests - all must succeed

Polish:
    1. Stwórz dekorator `mydecorator`
    2. Dekorator powinien mieć `wrapper` z parametrami `*args` i `**kwargs`
    3. Wrapper powinien wywoływać oryginalną funkcję z jej oryginalnymi
       parametrami i zwracać jej wartość
    4. Decorator powinien zwracać funckję `wrapper`
    5. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0
    >>> from inspect import isfunction

    >>> assert isfunction(mydecorator), \
    'Create mydecorator() function'

    >>> assert isfunction(mydecorator(lambda: ...)), \
    'mydecorator() should take function as an argument'

    >>> @mydecorator
    ... def echo(text):
    ...     return text

    >>> echo('hello')
    'hello'
"""

# type: Callable[[Callable], Callable]
def mydecorator():
    pass

Code 11.26. Solution
"""
* Assignment: Decorator Syntax Disable
* Complexity: easy
* Lines of code: 1 lines
* Time: 3 min

English:
    1. Modify decorator `disable`
    2. Decorator raises `PermissionError` and does not execute function
    3. Run doctests - all must succeed

Polish:
    1. Zmodyfikuj dekorator `disable`
    2. Dekorator podnosi `PermissionError` i nie wywołuje funkcji
    3. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0
    >>> from inspect import isfunction

    >>> assert isfunction(disable), \
    'Create disable() function'

    >>> assert isfunction(disable(lambda: ...)), \
    'disable() should take function as an argument'

    >>> @disable
    ... def echo(text):
    ...     print(text)

    >>> echo('hello')
    Traceback (most recent call last):
    PermissionError: Function is disabled
"""


# type: Callable[[Callable], Callable]
def disable(func):
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)

    return wrapper