realpython.com/primer-on-python-decorators/
2 Users
0 Comments
17 Highlights
0 Notes
Tags
Top Highlights
import functools def do_twice(func): @functools.wraps(func) def wrapper_do_twice(*args, **kwargs): func(*args, **kwargs) return func(*args, **kwargs) return wrapper_do_twice
import functools def decorator(func): @functools.wraps(func) def wrapper_decorator(*args, **kwargs): # Do something before value = func(*args, **kwargs) # Do something after return value return wrapper_decorator
This formula is a good boilerplate template for building more complex decorators.
@classmethod def unit_circle(cls): """Factory method creating a circle with radius 1""" return cls(1)
.unit_circle() is a class method. It’s not bound to one particular instance of Circle. Class methods are often used as factory methods that can create specific instances of the class.
def repeat(num_times): def decorator_repeat(func): @functools.wraps(func) def wrapper_repeat(*args, **kwargs): for _ in range(num_times): value = func(*args, **kwargs) return value return wrapper_repeat return decorator_repeat
import functools class CountCalls: def __init__(self, func): functools.update_wrapper(self, func) self.func = func self.num_calls = 0 def __call__(self, *args, **kwargs): self.num_calls += 1 print(f"Call {self.num_calls} of {self.func.__name__!r}") return self.func(*args, **kwargs) @CountCalls def say_whee(): print("Whee!")
The .__init__() method must store a reference to the function and can do any other necessary initialization. The .__call__() method will be called instead of the decorated function. It does essentially the same thing as the wrapper() function in our earlier examples. Note that you need to use the functools.update_wrapper() function instead of @functools.wraps. This @CountCalls decorator works the same as the one in the previous section: >>> >>> say_whee() Call 1 of 'say_whee' Whee! >>> say_whee() Call 2 of 'say_whee' Whee! >>> say_whee.num_calls 2
A Few Real World Examples
The solution is to use *args and **kwargs in the inner wrapper function. Then it will accept an arbitrary number of positional and keyword arguments
This means that only a reference to the function is passed. The function is not executed
Put simply: decorators wrap a function, modifying its behavior
To fix this, you need to make sure the wrapper function returns the return value of the decorated function. Change your decorators.py file
However, after being decorated, say_whee() has gotten very confused about its identity. It now reports being the wrapper_do_twice() inner function
To fix this, decorators should use the @functools.wraps decorator, which will preserve information about the original function. Update decorators.py again
Note that you are returning first_child without the parentheses. Recall that this means that you are returning a reference to the function first_child
In effect, the name say_whee now points to the wrapper() inner function
Glasp is a social web highlighter that people can highlight and organize quotes and thoughts from the web, and access other like-minded people’s learning.