Обертывание функций генератора в Python

Я пишу некоторый код, который просматривает структуру, которая может иметь циклические ссылки. Вместо того, чтобы явно выполнять проверки в начале рекурсивных функций, я подумал, что создам декоратор, который не позволял бы вызывать функцию более одного раза с одними и теми же аргументами.

Вот что я придумал. Как написано, это будет пытаться перебрать Nonetype и вызвать исключение. Я знаю, что могу исправить это, вернув, скажем, пустой список, но я хотел быть более элегантным. Есть ли способ узнать из декоратора, является ли декорируемая функция функцией генератора или нет? Таким образом, я могу условно поднять StopIteration, если это генератор, или просто вернуть None в противном случае.

previous = set()
def NO_DUPLICATE_CALLS(func):
    def wrapped(*args, **kwargs):
        if args in previous:
            print 'skipping previous call to %s with args %s %s' % (func.func_name, repr(args), repr(kwargs))
            return
        else:
            ret = func(*args, **kwargs)
            previous.add(args)
            return ret
    return wrapped

@NO_DUPLICATE_CALLS
def foo(x):
    for y in x:
        yield y

for f in foo('Hello'):
    print f

for f in foo('Hello'):
    print f
5
задан eric.frederich 20 June 2011 в 16:50
поделиться