У меня есть ситуация, в которой мне нужно подключить определенные функции, чтобы я мог проверять возвращаемые значения и отслеживать их.Это полезно для отслеживания, например, скользящих средних значений, возвращаемых методами / функциями.Однако эти методы / функции также могут быть генераторами.
Однако, если я не ошибаюсь, python обнаруживает генераторы при синтаксическом анализе и когда функция вызывается во время выполнения, он всегда возвращает генератор.Таким образом, я не могу просто сделать что-то вроде:
import types
def decorator(func):
average = None # assume average can be accessed by other means
def wrap(*args, **kwargs):
nonlocal average
ret_value = func(*args, **kwargs)
#if False wrap is still a generator
if isinstance(ret_value, types.GeneratorType):
for value in ret_value:
# update average
yield value
else:
# update average
return ret_value # ret_value can't ever be fetched
return wrap
И yield
в этом декораторе необходимо, так как мне нужно отслеживать значения, когда вызывающая программа выполняет итерацию этого декорированного генератора (то есть "в режиме реального времени" ).То есть я не могу просто заменить for
и yield
на values = list(ret_value)
и вернуть values
.(т.е.) Если func
является генератором, он должен оставаться генератором после декорирования.Но если func
является чистой функцией / методом, даже если else
выполняется, wrap
все еще остается генератором.Это означает, что ret_value
никогда не удастся получить.
Пример использования такого генератора может быть следующим:
@decorated
def some_gen(some_list):
for _ in range(10):
if some_list[0] % 2 == 0:
yield 1
else:
yield 0
def caller():
some_list = [0]
for i in some_gen(some_list):
print(i)
some_list[0] += 1 # changes what some_gen yields
Для примера с игрушкой могут быть более простые решения,но это просто для того, чтобы доказать свою точку зрения.
Может быть, я упускаю что-то очевидное, но я провел некоторое исследование и ничего не нашел.Самым близким, что я нашел, было это .Однако это все еще не позволяет декоратору проверять каждое значение, возвращаемое упакованным генератором (только первое).Есть ли у этого решение, или необходимы два типа декораторов (один для функций и один для декораторов)?