В некоторых случаях полезно накапливать результат, а затем получать его единым списком.
Реализуйте декоратор result_accumulator
, который модернизирует функцию с неопределенным количеством позиционных параметров следующим образом:
- Добавляет именованный параметр
method
со значением по умолчанию accumulate; - При вызове функции с параметром
method
равным accumulate, результат сохраняется в очередь (для каждой функции в собственную), а функция ничего не возвращает; - При вызове функции с параметром
method
равным drop, возвращается все накопленные результаты, а очередь сбрасывается.
Примечание
Ваше решение должно содержать только функции.
В решении не должно быть вызовов требуемых функций.
Пример
Ввод
@result_accumulator
def a_plus_b(a, b):
return a + b
print(a_plus_b(3, 5, method="accumulate"))
print(a_plus_b(7, 9))
print(a_plus_b(-3, 5, method="drop"))
print(a_plus_b(1, -7))
print(a_plus_b(10, 35, method="drop"))
Вывод
None
None
[8, 16, 2]
None
[-6, 45]
Ввод
@result_accumulator
def get_letters(text: str) -> str:
return ''.join(sorted(set(filter(str.isalpha, text.lower()))))
print(get_letters('Hello, world!'))
print(get_letters('Декораторы это круто =)'))
print(get_letters('Ехали медведи на велосипеде', method='drop'))
Вывод
None
None
['dehlorw', 'адекортуыэ', 'авдеилмнопсх']
Решение
Второй, чуть более сложный подход к теме декораторов. От предыдущего отличается тем, что нам надо добавить в вызываемую функцию дополнительный именованый параметр серьезно меняющий поведение функции, не “ломая” нормальный способ вызова функции.
Если раньше наша функция сразу возвращала результат, то теперь она его не возвращает, а “накапливает” и возвращает сразу списком только в том случае, если в качестве параметра был указано конкретное значение-сигнал.
Основная идея точно такая же как и в прошлой задаче. Мы для примера представляем как решили бы эту задачу в лоб и пишем внутреннюю функцию (wrapper – обертка), которая и будет для нас вызывать изначальную фунцкию, передавать ей параметры, принимать от нее результат и накапливать ее в список до тех пор, пока не настанет время вернуть нам этот список в качестве результата.
Я публикую два решения – первое частное, оно хорошо подходит для решения именно э того задания, но имеет концептуальный недостаток – оно предполагает что мы в любом случае хотим “накопить” результат. Второй вариант будет накапливать результат только если это прямо указано (отсутствие метода, метод накопления или использования метода “drop”). Вызов с любым другим методом будет проигнорирован.
Посмотреть код
Решение
# упрщенный вариант
def result_accumulator(func):
queue = []
def wrapper(*args, method='accumulate', **kwargs):
queue.append(func(*args, **kwargs))
if method == 'drop':
result = list(queue)
queue.clear()
return result
return wrapper
Решение
# концептуально более правильный вариант
def result_accumulator(func):
queue = []
def wrapper(*args, method='accumulate', **kwargs):
if method == 'accumulate':
queue.append(func(*args, **kwargs))
elif method == 'drop':
queue.append(func(*args, **kwargs))
result = queue[:]
queue.clear()
return result
return wrapper