TypeError: объект 'NoneType' не повторяется при применении декоратора к генератору - PullRequest
0 голосов
/ 02 января 2019

У меня есть функция декоратора, которую я хочу применить как к обычной функции, так и к генератору.Применительно к обычной функции она работает правильно.Однако при применении к генератору итерационный цикл внутри декоратора выполняется до конца, но после этого сценарий выдает ошибку:

TypeError: 'NoneType' object is not iterable

и выходит из сценария.

def decor(func):
    def wrapper(*args, **kwargs):
        func_name = func.__name__
        is_generator = "_generator" in func_name
        if is_generator:
            for item in func(*args, **kwargs):
                print(item)
        else:
            res = func(*args, **kwargs)
            print(res)
    return wrapper

@decor            
def f():
    return "a"

@decor    
def f_generator():
    for i in range(2):
        yield "b"

f()

""" Output: a """

for item in f_generator():
    print ("Processing item ", item)

"""
Output:
b
b
Traceback (most recent call last):
  File "test.py", line 27, in <module>
      for item in f_generator():
TypeError: 'NoneType' object is not iterable
"""

Кроме того, когда декоратор применяется к генератору, print ("Processing item ", item) вызова внешнего генератора не выполняется.После удаления декоратора из генератора я могу вызвать генератор, и он работает правильно.

Как исправить проблему, чтобы я мог применить декоратор к генератору и заставить его работать без ошибок?Попытка обработать ошибку с исключением исключает ошибку, и сценарий выполняется полностью, но затем print ("Processing item ", item) все еще не выполняется.

Ответы [ 2 ]

0 голосов
/ 02 января 2019

проблема с вашим последним циклом.вы перебираете функцию wrapper, так как это то, что вы получаете при вызове f_generator(), а оболочка не является итератором.

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

0 голосов
/ 02 января 2019

Когда вы добавляете @decorator, f_generator() в for item in f_generator(): на самом деле decor(f_generator). Поскольку decor() ничего не возвращает и не возвращает, само по себе оно не повторяется, вам следует добавить yield item вокруг for item in func(*args, **kwargs):

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...