Skip to content
This repository was archived by the owner on Jul 2, 2024. It is now read-only.

Commit 66510ce

Browse files
committed
Added inner-wrapper/decorator with arguments
Signed-off-by: Serhii Horodilov <sgorodil@gmail.com>
1 parent c045a25 commit 66510ce

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

src/basics/decorators.txt

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,3 +251,96 @@ once more time again, and again, and again...
251251
methods as the target and delegates to it all requests it receives.
252252
However, the wrapper may alter the result by doing something either before
253253
or after it passes the request to the target.
254+
255+
Passing arguments to the wrapper
256+
================================
257+
258+
Until now the examples use *simple* decorators. But what if the decorated
259+
function gets some arguments? This will cause ``TypeError`` exception that tell
260+
that "arguments are missed". This can be fixed with just passing arguments to
261+
the ``wrapper`` inner function.
262+
263+
.. code-block:: python
264+
265+
import logging
266+
from typing import Callable
267+
268+
logging.basicConfig(level=logging.INFO)
269+
logger = logging.getLogger(__name__)
270+
271+
272+
def log(func: Callable) -> Callable:
273+
def wrapper(x, y):
274+
logger.info("%s called", func.__name__)
275+
return func(x, y)
276+
277+
return wrapper
278+
279+
280+
@log
281+
def sum_numbers(x, y):
282+
return x + y
283+
284+
If case you're trying to make a generic decorator, you may pass ``*args`` and
285+
``**kwargs`` instead of exact arguments:
286+
287+
.. code-block:: python
288+
289+
from typing import Callable
290+
291+
292+
def generic_decorator(func: Callable) -> Callable:
293+
def wrapper(*args, **kwargs):
294+
... # do something before
295+
result = func(*args, **kwargs)
296+
... # do something after
297+
298+
return result
299+
300+
return wrapper
301+
302+
Passing arguments to decorator
303+
==============================
304+
305+
At last it's time to know how to pass arguments to the decorator.
306+
Here is a simple implementation of ``defer`` decorator which deferred
307+
the function execution for some time:
308+
309+
.. code-block:: python
310+
311+
import time
312+
from typing import Callable
313+
314+
315+
def defer(seconds: int = 3) -> Callable:
316+
def decorator(func: Callable) -> Callable:
317+
def wrapper(*args, **kwargs):
318+
started_at = time.perf_counter()
319+
time.sleep(seconds)
320+
result = func(*args, **kwargs)
321+
completed_in = round(time.perf_counter() - started_at, 2)
322+
print("Completed in %.2f" % completed_in)
323+
324+
return result
325+
326+
return wrapper
327+
328+
return decorator
329+
330+
331+
@defer()
332+
def function_a():
333+
return 42
334+
335+
336+
@defer(10)
337+
def function_b():
338+
return 24
339+
340+
341+
.. code-block::
342+
343+
function_a()
344+
Completed in 3.00
345+
function_b()
346+
Completed in 10.00

0 commit comments

Comments
 (0)