Files
python-VM/learning/decorators/decorator.py

205 lines
5.8 KiB
Python
Executable File

import itertools
import functools
from time import perf_counter, sleep
import sys
def do_twice(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for _ in itertools.repeat(None, 2):
func(*args, **kwargs)
return func(*args, **kwargs)
return wrapper
def timer(func):
@functools.wraps(func)
def wrapper_timer(*args, **kwargs):
start_time = perf_counter()
value = func(*args, **kwargs)
end_time = perf_counter()
run_time = end_time - start_time
print(f'Finished {func.__name__!r} in {run_time:.4f} secs')
return value
return wrapper_timer
def debug(func):
""" Print the function signature and return the value """
@functools.wraps(func)
def wrapper_debug(*args, **kwargs):
args_repr = [repr(a) for a in args]
kwargs_repr = [f'{k}={v!r}' for k, v in kwargs.items()]
signature = ', '.join(args_repr + kwargs_repr)
print(f'Calling {func.__name__}({signature})')
value = func(*args, **kwargs)
print(f'{func.__name__!r} returned {value!r}')
return value
return wrapper_debug
def slow_down(func):
@functools.wraps(func)
def wrapper_slow_down(*args, **kwargs):
sleep(1)
return func(*args, **kwargs)
return wrapper_slow_down
def repeat(num: int):
def decorator_repeat(func: callable):
@functools.wraps(func)
def wrapper_repeat(*args: list, **kwargs: dict):
for _ in range(num):
value = func(*args, **kwargs)
return value
return wrapper_repeat
return decorator_repeat
def repeatN(_func=None, *, num=2):
def decorator_repeatN(func):
@functools.wraps(func)
def wrapper_repeatN(*args, **kwargs):
for _ in range(num):
value = func(*args, **kwargs)
return value
return wrapper_repeatN
if _func is None:
return decorator_repeatN
else:
return decorator_repeatN(_func)
def repeat_partial(func=None, *, num=2):
if func is None:
return functools.partial(repeat_partial, num=num)
@functools.wraps(func)
def repeat_partial_wrapper(*args, **kwargs):
for _ in range(num):
value = func(*args, **kwargs)
return value
return repeat_partial_wrapper
# def count_calls(func: callable):
# @functools.wraps(func)
# def wrapper_count_calls(*args, **kwargs):
# wrapper_count_calls.num_calls += 1
# print(f'Call {wrapper_count_calls.num_calls} of {func.__name__!r}')
# return func(*args, **kwargs)
# wrapper_count_calls.num_calls = 0
# print(wrapper_count_calls.num_calls)
# return wrapper_count_calls
# def count_calls(func: callable):
# num_calls = 0
# print(num_calls)
# @functools.wraps(func)
# def wrapper_count_calls(*args, **kwargs):
# nonlocal num_calls
# num_calls += 1
# print(f'Call {num_calls} of {func.__name__}')
# return func(*args, **kwargs)
# return wrapper_count_calls
def count_calls(func=None, *, num=0):
if func is None:
return functools.partial(count_calls, num=num)
@functools.wraps(func)
def wrapper_count_calls(*args, **kwargs):
wrapper_count_calls.num += 1
print(f'Call {wrapper_count_calls.num} of {func.__name__}')
return func(*args, **kwargs)
wrapper_count_calls.num = num
return wrapper_count_calls
class Counter(object):
"""docstring for Counter"""
def __init__(self, func):
print('start init')
super(Counter, self).__init__()
functools.update_wrapper(self, func)
self.func = func
self.num_calls = 0
print('finished init')
def __call__(self, *args, **kwargs):
print('start call')
self.num_calls += 1
print(f'Call {self.num_calls} of {self.func.__name__!r}')
print('finished call')
return self.func(*args, **kwargs)
# class slowDown(object):
# """docstring for slowDown"""
# def __init__(self, rate):
# if callable(rate):
# self.func = rate
# self.rate = 1
# else:
# self.rate = rate
# def __get__(self, obj, type=None):
# return functools.partial(self, obj)
# def __call__(self, *args, **kwargs):
# if not hasattr(self, 'func'):
# self.func = args[0]
# return self
# sleep(self.rate)
# self.func(*args, **kwargs)
class slowDown(object):
"""docstring for Slow_Down"""
def __init__(self, rate=1):
print('init')
self.rate = rate
def __call__(self, func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('wrapper')
sleep(self.rate)
func(*args, **kwargs)
print('call finished')
print(self, func)
return wrapper
# class slowDown(object):
# """docstring for slowDown"""
# def __init__(self, rate):
# if callable(rate):
# self.func = rate
# self.rate = 1
# print(f'no args, {locals()}, func={self.func}, rate={self.rate},\
# self={self}')
# else:
# self.rate = rate
# print(f'args set, rate={self.rate}')
# def __get__(self, obj, type=None):
# print(f'get called, self={self}, obj={obj}, type={type}')
# return functools.partial(self, obj)
# def __call__(self, *args, **kwargs):
# print(f'call called, rate={self.rate}, args={args}'
# f', kwargs={kwargs} ,self={self}')
# print(f'locals = {locals()}')
# if not hasattr(self, 'func'):
# self.func = args[0]
# print(f'args set, setting self.func to {self.func}')
# return self
# sleep(self.rate)
# self.func(*args, **kwargs)