B13 - decorators
source: L Ramalho, Fluent Python, O'Riley(2022)
decorator
- a callable that takes another function/class as an argument, which may perform some processing, and returns or replaces it with another function/class or callable object
- function markers that enhance their behaviour
@decorate
def target():
print("running")
## same as
def target():
print("running")
target = decorate(target)
def deco(func):
def inner():
print("running inner()")
return inner
@deco
def target():
print("running target()")
target()
running inner()
-
here, running
target()runsinner() -
this is because the decorator function passes
inner -
if the wrapper, ie.
inner, is removed,targetruns without being called -
to run
targer()as well, callfunc()insideinner() -
if the decorated function accepts arguments, the wrapper function must accept them too
def deco(func):
def inner(*args, **kwargs): ## accepts any arguements
print("running inner()")
func()
return inner
@deco
def target(destination):
print("running target at {destination}")
target()
registry = []
def register(func):
print(f"Registering {func}")
registry.append(func)
return func
@register
def f1():
print("Running f1")
@register
def f2():
print("Running f2")
def f3():
print("Running f3")
def main():
print("Running main")
print('registry:', registry)
f1()
f2()
f3()
if __name__ == "__main__":
main()
Registering <function f1 at 0x000001C974E58A40>
Registering <function f2 at 0x000001C974E58900>
Running main
registry: [<function f1 at 0x000001C974E58A40>, <function f2 at 0x000001C974E58900>]
Running f3
- here,
registerruns twice before anything else, while the defined functions only run when explicitly called - if it is imported,
registeris run, but not the functions - so the decorators are executed as soon as the module is imported, but the decorated functions run only when explicitly invoked
standard library
memorization
import functools
@functools.cache
-
an optimization technique that saves the results of previous invocations, so computations need not be repeated on previously used arguments
-
@lru_cache, which stands for last recently used, is bounded by themaxsizeparameter -
it can hold at most 128 entries
-
@lru_cache(maxsize = 2**20, typed = True- the
maxsizeshould be a power of 2 to optimize the performance typeddetermines whether the results of different argument types are stored separately, and isFalseby default
- the