• Home
  • Explore

Primer on Python Decorators – Real Python

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

Ready to highlight and find good content?

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.

AboutPrivacyTerms

© 2023 Glasp Inc. All rights reserved.