4 ms·
This cheat sheet is of quite poor quality: the very second thing it tries to explain is decorator: A decorator is a callable that manipulates and returns a fun
by mathfailure 3y ago
This cheat sheet is of quite poor quality: the very second thing it tries to explain is decorator:
A decorator is a callable that manipulates and returns a function.
# wraps decorator copies metadata of decorated function (func) to wrapped function (out)
from functools import wraps
def show_call(func):
"""
Print function name and arguments each time it is called.
"""
@wraps(func)
def out(*args, **kwds):
print(func.__name__, args, kwds)
return func(*args, **kwds)
return out
@show_call
def add(x, y):
return x + y
This example uses a decorator function show_call() when calling function add(), but that decorator function itself is not a simple function, but some weirdo that actually defines another function out() with *args and **kwargs THAT IS ALSO ALREADY DECORATED (with function wraps())!
I couldn't have thought of a worse example for a cheat sheet.
A cheat sheet is supposed to give short simple explanations/demonstrations.
That example shouldn't have a nested function, it should demonstrate just 1 decorator function and 1 decorated function and none of these functions should be nested and they also shouldn't use arguments with asterisks (if possible).
Feedback from someone still failing to understand what decorator is, especially after reading the cheat sheet.
- jonathrg 3y agoA decorator is a function that takes a function and returns a modified function - how would you write a decorator without nesting functions? Wrapping the inner function of the decorator with @wraps is quite common - one might consider it a bug in the language that the @wraps feature is not built into the decorator mechanism. But it is a valid point that decorators should not be presented that early.
- aunderscored 3y agoDecorators don't have to return functions. It's just nice to. The result of the call is bound to the name
- ptx 3y agoIt is confusing, but it's also kind of the standard pattern for decorators in Python, so it's a useful example. The decorator syntax itself is just simple syntax sugar for replacing the decorated function (add) with the return value of the decorator function (show_call). The example is essentially equivalent to this: def show_call(func): ... def add(x, y): return x + y add = show_call(add) So show_call has to return the function we want as a replacement, which is the nested "out" function here. The "@wraps" thing is not strictly necessary but updates the new function object to have the same name as the original.
- Spivak 3y agoYeah the standard "I'm gonna make a decorator for this" template is def decorate(<decorator args>): def _decorate(<thing to be decorated>): pass return _decorate @decorate(foo=1) def myfunc(): pass
- EdwardDiego 3y agoAnd then there's class decorators (as in, they're a class, not a function). Which are fun, there's two separate paths for args vs no-args.
- kmh 2y agoI've revised the decorator section. Perhaps it may be clearer now. Feedback welcome.