from functools import wraps from copy import deepcopy def no_side_effects_decorator(func): @wraps(func) def inner(*args, **kwargs): if isinstance(args[0], (list, dict, set)): copeed_args = tuple([args[0].copy(), *args[1:]]) else: copeed_args = args return func(*copeed_args, **kwargs) return inner @no_side_effects_decorator def add_element(data, element): data.append(element) return data ''' def add_element(data, key, value=None): data[key] = value return data ''' def add_args(func): @wraps(func) def inner(*args, **kwargs): modifed_args = ('begin', ) + args + ('end', ) return func(*modifed_args, **kwargs) return inner @add_args def concatenate(*args): """ Возвращает конкатенацию переданных строк """ return ', '.join(args) def explicit_args(func): @wraps(func) def inner(*args, **kwargs): if len(args): print('Вы не можете передать позиционные аргументы. Используйте именованный способ передачи значений') return else: return func(*args, **kwargs) return inner @explicit_args def add(a: int, b: int) -> int: '''Возвращает сумму двух чисел''' return a + b def reverse(func): @wraps(func) def inner(*args, **kwargs): reversed_args = args[::-1] return func(*reversed_args) return inner def monkey_patching(func): @wraps(func) def inner(*args, **kwargs): patched_args = ('Monkey', )*len(args) patched_kwargs = {key:'patching' for key, _ in kwargs.items()} return func(*patched_args, **patched_kwargs) return inner @monkey_patching def info_kwargs(**kwargs): """Выводит информацию о переданных kwargs""" for k, v in sorted(kwargs.items()): print(f'{k} = {v}') def counting_calls(func): @wraps(func) def inner(*args, **kwargs): inner.call_count += 1 inner.calls.append({'args': args, 'kwargs':kwargs}) return func(*args, **kwargs) setattr(inner, 'call_count', 0) setattr(inner, 'calls', []) return inner @counting_calls def add(a: int, b: int) -> int: '''Возвращает сумму двух чисел''' return a + b def check_count_args(func): @wraps(func) def inner(*args, **kwargs): if (len(args) + len(kwargs)) == 2: return func(*args, **kwargs) elif (len(args) + len(kwargs)) < 2: print("Not enough arguments") else: print("Too many arguments") return inner def cache_result(func): cache = {} @wraps(func) def inner(*args, **kwargs): nonlocal cache key = (args, tuple(kwargs.items())) if key in cache.keys(): print(f'[FROM CACHE] Вызов {inner.__name__} = {cache[key]}') return cache[key] else: res = func(*args, **kwargs) cache[key] = res return res return inner @cache_result def multiply(a, b): return a * b def test(*args, **kwargs): pass def main(): print(add(10, b=20)) print(add(7, 5)) print(add(12, 45)) print('Количество вызовов =', add.call_count) print(add.calls[2]) print(add(b=11, a=22)) print(add.calls[3]) # print(multiply(4, 5)) # Вызываем 1й раз функцию с аргументами 4 и 5. Идет сохранение результата # print(multiply(4, 5)) # При повторном вызове достаем из кеша # print(multiply(5, 8)) # Впервые вызывает с аргументами 5 и 8 # print(multiply(5, 8)) # Достаем из кеша результат вызова multiply(5, 8) # print(multiply(5, 8)) # Вновь достаем из кеша # print(multiply(-3, 7)) # Впервые вычисляем результат вызова multiply(-3, 7), сохраняем в кеше # print(multiply(-3, 7)) # Достаем из кеша multiply(-3, 7) # info_kwargs(first_name="John", last_name="Doe", age=33) # info_kwargs(c=43, b= 32, a=32) # print(info_kwargs.__name__) # print(info_kwargs.__doc__.strip()) # print(add(10, 20)) # print(concatenate('hello', 'world', 'my', 'name is', 'Artem')) # print(concatenate('my', 'name is', 'Artem')) # print(concatenate.__name__) # print(concatenate.__doc__.strip()) # my_list = [1, 2, 3] # print('Результат вызова =', add_element(my_list, 4)) # print('Результат вызова =', add_element(my_list, 5)) # my_dict = {1: 'Hello', 2: 'World'} # print('Результат вызова =', add_element(my_dict, 4, 'four')) # print(my_list) # print(add_element.__name__) # test(my_list) if __name__ == '__main__': main()