decorator_4.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. from functools import wraps
  2. import time
  3. '''
  4. Такой декоратор работать не будет
  5. '''
  6. '''
  7. def html_tag(func, name_tag='h1'):
  8. def inner(*args, **kwargs):
  9. result = func(*args, **kwargs)
  10. return f'<{name_tag}>{result}</{name_tag}>'
  11. return inner
  12. '''
  13. '''
  14. def decorator_factory(a, b):
  15. print('Запуск функции создания декоратора')
  16. def decorator(fn):
  17. print('Запуск декоратора')
  18. def wrapper(*args, **kwargs):
  19. print('Запуск функции wrapper')
  20. print('Переданные аргументы: ', a, b)
  21. return fn(*args, **kwargs)
  22. return wrapper
  23. return decorator
  24. '''
  25. '''
  26. Можно раскрыть следующей записью
  27. decorator = decorator_factory() # получаем декоратор из decorator_factory
  28. original_func = decorator(original_func) # декорируем
  29. Или есть еще вариант
  30. original_func = decorator_facotry()(original_func)
  31. '''
  32. '''
  33. @decorator_factory(10, 20) # Обратите внимание на оператор вызова
  34. def original_func():
  35. print('Запуск оригинальной функции')
  36. '''
  37. '''
  38. Рабочий вариант декоратора
  39. '''
  40. def html_tag(name_tag='h1'):
  41. def decorator(func):
  42. @wraps(func)
  43. def inner(*args, **kwargs):
  44. result = func(*args, **kwargs)
  45. return f'<{name_tag}>{result}</{name_tag}>'
  46. return inner
  47. return decorator
  48. @html_tag(name_tag='table')
  49. @html_tag('td')
  50. @html_tag()
  51. @html_tag('p')
  52. def say_hello_to(name, surname):
  53. return f'Hello {name} {surname}'
  54. def cached_with_expiry(expiry_time):
  55. def decorator(original_function):
  56. cache = {} # словарь для хранения кеша
  57. def wrapper(*args, **kwargs):
  58. key = (*args, *kwargs.items())
  59. if key in cache:
  60. cached_value, cached_timestamp = cache[key]
  61. if time.time() - cached_timestamp < expiry_time:
  62. return f'[CACHED] - {cached_value}'
  63. result = original_function(*args, **kwargs)
  64. cache[key] = (result, time.time())
  65. return result
  66. return wrapper
  67. return decorator
  68. @cached_with_expiry(expiry_time=5)
  69. def get_product(x, y):
  70. return x*y
  71. def multiply_result_by(n):
  72. def decorator(func):
  73. @wraps(func)
  74. def wrapper(*args, **kwargs):
  75. result = func(*args, **kwargs)
  76. return n*result
  77. return wrapper
  78. return decorator
  79. def limit_query(n):
  80. def decorator(func):
  81. limit = n
  82. @wraps(func)
  83. def wrapper(*args, **kwargs):
  84. nonlocal limit
  85. if limit == 0:
  86. print(f'Лимит вызовов закончен, все {n} попытки израсходованы')
  87. return None
  88. else:
  89. limit -= 1
  90. return func(*args, **kwargs)
  91. return wrapper
  92. return decorator
  93. def monkey_patching(arg='Monkey', kwarg='patching'):
  94. def decorator(func):
  95. @wraps(func)
  96. def wrapper(*_args, **_kwargs):
  97. patched_args = (arg, )*len(_args)
  98. patched_kwargs = {key:kwarg for key, _ in _kwargs.items()}
  99. return func(*patched_args, **patched_kwargs)
  100. return wrapper
  101. return decorator
  102. @monkey_patching(kwarg='Duper')
  103. def print_args_kwargs(*args, **kwargs):
  104. for i, value in enumerate(args):
  105. print(i, value)
  106. for k, v in sorted(kwargs.items()):
  107. print(f'{k} = {v}')
  108. def pass_arguments(*args_, **kwargs_):
  109. def decorator(func):
  110. @wraps(func)
  111. def wrapper(*args, **kwargs):
  112. print(args_, kwargs_)
  113. return func(*args, **kwargs)
  114. return wrapper
  115. return decorator
  116. @pass_arguments(s='Когда', w='-', r='нибудь!')
  117. def concatenate(**kwargs):
  118. result = ""
  119. for arg in kwargs.values():
  120. result += str(arg)
  121. return result
  122. def pass_arguments(*args_, **kwargs_):
  123. def decorator(func):
  124. @wraps(func)
  125. def wrapper(*args, **kwargs):
  126. new_args = args + args_
  127. new_kwargs = kwargs | kwargs_
  128. return func(*new_args, **new_kwargs)
  129. return wrapper
  130. return decorator
  131. def convert_to(type_):
  132. def decorator(func):
  133. @wraps(func)
  134. def wrapper(*args, **kwargs):
  135. return type_(func(*args, **kwargs))
  136. return wrapper
  137. return decorator
  138. @convert_to(str)
  139. def add_values(a, b):
  140. return a + b
  141. '''
  142. def validate_all_args_str(func):
  143. def wrapper(*args, **kwargs):
  144. if len([True for x in args if type(x) == str]) == len(args):
  145. return func(*args, **kwargs)
  146. else:
  147. print('Все аргументы должны быть строками')
  148. return wrapper
  149. '''
  150. def validate_all_args(type_):
  151. def decorator(func):
  152. @wraps(func)
  153. def wrapper(*args, **kwargs):
  154. if len([True for x in args if type(x) == type_]) == len(args):
  155. return func(*args, **kwargs)
  156. else:
  157. print(f'Все аргументы должны принадлежать типу {type_}')
  158. return wrapper
  159. return decorator
  160. @validate_all_args(set)
  161. def print_args_kwargs(*args, **kwargs):
  162. for i, value in enumerate(args):
  163. print(i, value)
  164. for k, v in sorted(kwargs.items()):
  165. print(f'{k} = {v}')
  166. def compose(*args_):
  167. def decorator(func):
  168. @wraps(func)
  169. def wrapper(*args, **kwargs):
  170. result = func(*args, **kwargs)
  171. for f in args_:
  172. result = f(result)
  173. return result
  174. return wrapper
  175. return decorator
  176. def double_it(a):
  177. return a * 2
  178. def increment(a):
  179. return a + 1
  180. @compose(double_it, increment)
  181. def get_sum(*args):
  182. return sum(args)
  183. def add_attrs(**kwargs_):
  184. def decorator(func):
  185. @wraps(func)
  186. def wrapper(*args, **kwargs):
  187. return func(*args, **kwargs)
  188. for key, value in kwargs_.items():
  189. setattr(wrapper, key, value)
  190. return wrapper
  191. return decorator
  192. @add_attrs(test=True, ordered=True)
  193. def add(a, b):
  194. return a + b
  195. def main():
  196. print(add(10, 5))
  197. print(add.test)
  198. print(add.ordered)
  199. # print(get_sum(5))
  200. # print(get_sum(20, 10))
  201. # print(get_sum(5, 15, 25))
  202. # print_args_kwargs([], [1], [1, 2], b=set(), w=set())
  203. # print_args_kwargs(1, 2, 3, 4, b=300, w=40, t=50, a=100)
  204. # result = add_values(10, 20)
  205. # print(f"Результат: {result}, тип результата {type(result)}")
  206. # print(add(5, 4, 6, a=1, b=2))
  207. # print(concatenate(a="Я", b="Выучу", c="Этот", d="Питон", e="!"))
  208. # print_args_kwargs(1, 2, 3, 4, b=300, w=40, t=50, a=100)
  209. '''
  210. print(get_product(23, 5)) # Вычисляем в первый раз
  211. print(get_product(23, 5)) # Во второй раз срабатывает кеш
  212. time.sleep(5)
  213. print(get_product(23, 5)) # Кеш просрочился, поэтому вновь вычисляется значение
  214. '''
  215. # original_func()
  216. # print(say_hello_to('Vasiliy', 'Ytkin'))
  217. if __name__ == '__main__':
  218. main()