functools module learning

1. partial(func, /, *args, **kwargs)

  • Encapsulate the original function and return an partial objectobject, which can be called directly
  • Fixing some parameters of the original function is equivalent to adding a fixed default value
    to the original function, which is equivalent to the following code:
def partial(func, /, *args, **kwargs):
    def newfunc(*fargs, **fkwargs):
        newkwargs = {**kwargs, **fkwargs}
        return func(*args, *fargs, **newkwargs)
    newfunc.func = func
    newfunc.args = args
    newfunc.kwargs = kwargs
    return newfunc

For example, you need a int()function that converts binary by default :

>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo.__doc__ = 'Convert base 2 string to an int.'
>>> basetwo('10010')
18

2. partialmethod(func, /, *args, **kwargs)

  • Same as partialusage, specifically used in class definition (because the first parameter in the class definition is required self/clsby default , so it is partialnot applicable)
  • In the class, regardless of the ordinary method, staticmethodit classmethodstill abstractmethodapplies

E.g:

class Cell:
    def __init__(self):
        self._alive = False
    
    @property
    def alive(self):
        return self._alive
    
    def set_alive(self, state):
        self._alive = bool(state)
    set_alive = partialmethod(set_state, True)
    set_dead = partialmethod(set_state, False)

>>> c = Cell()
>>> c.alive
False
>>> c.set_alive()
>>> c.alive
True

3. update_wrapper(wrapper, warpped, assigned=WRAPPER_ASSIGNMEDTS, updated=WRAPPER_UPDATES)

  • Update wrapper to make it look more like wrapped
  • Mainly used in decorators, wrap the decorated function, and return an updated decoration function. If the decoration function is not updated, then the metadata of the returned function will come from the decorator, not the original function
  • Two optional parameters used to specify which properties of the original function directly assigned decorative function, which properties need to be updated accordingly decorative function. The default value is a constant-level module WRAPPER_ASSIGNMENTS(assignment decorative function __module__, __name__, __qualname__, __annotations__and __doc__attributes) and the WRAPPER_UpDATED(updated decor Function __dict__properties)

4. wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updasted=WRAPPER_UPDATES)

  • Simplify the calling update_wrapperprocess, use as a decorator
  • Equivalent topartial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated)

E.g:

def my_decorator(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        print('Calling decorated function')
        return f(*args, **kwargs)
    return wrapper

@my_decorator
def example():
    """Docstring"""
    print('Called example function')

>>> example()
Calling decorated function
Called example function
>>> example.__name__
'example'
>>> example.__doc__
'Docstring'

If not used wraps, the name of the decorated function will be wrapper, and the original function example's docstring will be lost.

5. singledispatch(func)

  • Used as a decorator, transforming the decorated function into a generic function
  • Perform different operations based on the type of the first parameter

E.g:

@singledispatch
def fun(arg, verbose=False):
    if verbose:
        print('Let me just say,', end='')
    print(arg)

@fun.register(int)
def _(arg, verbose=False):
    if verbose:
        print('Strength in numbers, eh?', end='')
    print(arg)

@fun.register(list)
def _(arg, verbose=False)
    if verbose:
        print('Enumerate this: ')
    for i, elem in enumerate(arg):
        print(i, elem)


>>> fun('Hello World')
Hello World
>>> fun('test', verbose=True)
Let me just say, test
>>> fun(123, verbose=True)
Strength in numbers, eh? 123
>>> fun(['Issac', 'Chaplin', 'Mr Bean'], verbose=True)
Enumerate this:
0 Issac
1 Chaplin
2 Mr Bean

You can use "function type annotations" instead of explicitly specifying types above

@fun.register
def _(arg: int, verbose=False):
    pass

6. singledispatchmethod(func)

  • Decorate the method as a generic function
  • Dispatch to perform different operations based on the first non- selfor non - clsparameter type
  • Can be nested with other decorators, but singledispatchmethodit dispatcher.registermust be in the outermost layer
  • Other usages are the singledispatchsame

E.g:

class Negator:
    @singledispatchmethod
    @classmethod
    def neg(cls, arg):
        raise NotImplementedError("Cannot negate a")
    
    @neg.register
    @classmethod
    def _(cls, arg: int):
        return -arg
    
    @neg.register
    @classmethod
    def _(cls, arg: bool):
        return not arg

7. cached_property(func)

  • Convert the method to an attribute, @propertysimilar to
  • The decorated method is calculated only once, and then cached as a normal instance attribute
  • Requires instance to have variable __dict__attributes (not available in metaclasses or classes __slots__not included __dict__in the declaration )

E.g:

class DataSet:
    def __init__(self, sequence_of_numbers):
        self._data = sequence_of_numbers
    
    @cached_property
    def stdev(self):
        return statistics.stdev(self._data)
    
    @cached_property
    def variance(self):
        return statistics.variance(self._data)

cached_propertyThe bottom layer is a non-data descriptor. During functhe first calculation, the result is stored in an attribute of the same name (in the instance __dict__) of the instance. Since the priority of the instance attribute is greater than the non-data descriptor, all subsequent calls are only directly Take instance attributes without recalculating

8. lru_cache(user_function) / lru_cache(maxsize=128, typed=False)

  • Cache the maxsizeresult of the last call of the decorated function
  • maxsizeIf set to None, the LRU cache mechanism will be unavailable and the cache will grow indefinitely. maxsizeThe value is preferably a power of 2
  • Since the bottom layer uses a dictionary to cache the results, the parameters of the decorated function must be hashable.
  • Different parameter modes will be cached separately as unused entries, for example, f(a=1, b=2)and f(b=2, a=1)will be used as two caches
  • If typedset to True, different types of function parameters will be cached separately, for example f(3)andf(3.0)

E.g:

@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)

Guess you like

Origin www.cnblogs.com/thunderLL/p/12697672.html