3.9. Standard Library Functools

3.9.1. Wraps

  • from functools import wraps

  • @wraps(func)

def my_decorator(func):
    def wrapper(*args, **kwargs):
        """wrapper docstring"""
        return func(*args, **kwargs)
    return wrapper


@my_decorator
def my_function(x):
    """my_function docstring"""
    print(x)


print(my_function.__name__)
# wrapper

print(my_function.__doc__)
# wrapper docstring
from functools import wraps


def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """wrapper docstring"""
        return func(*args, **kwargs)
    return wrapper


@my_decorator
def my_function(x):
    """my_function docstring"""
    print(x)


print(my_function.__name__)
# my_function

print(my_function.__doc__)
# my_function docstring

3.9.2. Cached Property

  • from functools import cached_property

  • @cached_property(func)

import statistics
from functools import cached_property


class Iris:
    def __init__(self, *args):
        self._measurements = args

    @cached_property
    def mean(self):
        return statistics.mean(self._measurements)

    @cached_property
    def stdev(self):
        return statistics.stdev(self._measurements)


flower = Iris(5.1, 3.5, 1.4, 0.2)
flower.stdev()
flower.mean()

3.9.3. LRU (least recently used) cache

  • from functools import lru_cache

  • @lru_cache(maxsize=None)

from functools import lru_cache


@lru_cache(maxsize=None)
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

[fib(n) for n in range(16)]
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]

fib.cache_info()
# CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)

3.9.4. Assignments

3.9.4.1. Decorator Functools Func

English
  1. Use code from "Input" section (see below)

  2. Use functools.wraps in correct place

  3. Compare result with "Output" section (see below)

Polish
  1. Użyj kodu z sekcji "Input" (patrz poniżej)

  2. Użyj functools.wraps w odpowiednim miejscu

  3. Porównaj wyniki z sekcją "Output" (patrz poniżej)

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


@mydecorator
def hello():
    """Hello Docstring"""
    pass
Ouput
print('Function:', hello.__name__)
# Function: hello

print('Doctring:', hello.__doc__)
# Doctring: Hello Docstring

3.9.4.2. Decorator Functools Args

English
  1. Use code from "Input" section (see below)

  2. Use functools.wraps in correct place

  3. Compare result with "Output" section (see below)

Polish
  1. Użyj kodu z sekcji "Input" (patrz poniżej)

  2. Użyj functools.wraps w odpowiednim miejscu

  3. Porównaj wyniki z sekcją "Output" (patrz poniżej)

def mydecorator(happy=True):
    def decorator(func):
        def wrapper(*args, **kwargs):
            return func(*args, **kwargs)
        return wrapper
    return decorator


@mydecorator(happy=False)
def hello():
    """Hello Docstring"""
    pass
Ouput
print('Function:', hello.__name__)
# Function: hello

print('Doctring:', hello.__doc__)
# Doctring: Hello Docstring

3.9.4.3. Decorator Functools Cls

English
  1. Use code from "Input" section (see below)

  2. Modify code to restore docstring and name from decorated class

  3. Compare result with "Output" section (see below)

Polish
  1. Użyj kodu z sekcji "Input" (patrz poniżej)

  2. Zmodyfikuj kod aby przywrócić doctring oraz nazwę z dekorowanej klasy

  3. Porównaj wyniki z sekcją "Output" (patrz poniżej)

Input
def mydecorator(cls):
    class Wrapper(cls):
        pass
    return Wrapper


@mydecorator
class Hello:
    """Hello Docstring"""


hello = Hello()
Output
print('Class:', hello.__name__)
# Class: Hello

print('Doctring:', hello.__doc__)
# Doctring: Hello Docstring