уступить в Python - PullRequest
       42

уступить в Python

49 голосов
/ 18 июня 2011

согласно ответу на этот вопрос , разрыв доходности в C # эквивалентен возврату в python. в нормальном случае «возврат» действительно останавливает генератор. Но если ваша функция ничего не делает, кроме возврата, вы получите None, а не пустой итератор, который возвращается yield break в C #

def generate_nothing():
    return

for i in generate_nothing():
    print i

вы получите TypeError: объект 'NoneType' не повторяется. но если я добавлю никогда не запускать yield до return, эта функция вернет то, что я ожидаю.

def generate_nothing():
    if False: yield None
    return

, если работает, но кажется проводным. У кого есть идея получше?

спасибо,

Ответы [ 4 ]

45 голосов
/ 18 июня 2011
def generate_nothing():
    return
    yield
44 голосов
/ 07 января 2013

Хороший способ справиться с этим - поднять StopIteration , которое возникает, когда у вашего итератора ничего не осталось, и вызывается next().Это также изящно вырвется из цикла for, и внутри цикла ничего не будет выполнено.

Например, при наличии кортежа (0, 1, 2, 3) Я хочу получить перекрывающиеся пары ((0, 1), (1, 2), (2, 3)).Я мог бы сделать это так:

def pairs(numbers):
    if len(numbers) < 2:
        raise StopIteration

    for i, number in enumerate(numbers[1:]):
        yield numbers[i], number

Теперь pairs безопасно обрабатывает списки с 1 номером или меньше.

6 голосов
/ 18 июня 2011
def generate_nothing():
    return iter([])
1 голос
/ 18 июня 2011

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

>>> def f():
...   return

>>> def g():
...   if False: yield 
#in Python2 you can use 0 instead of False to achieve the same result


>>> from dis import dis
>>> dis(f)
2           0 LOAD_CONST               0 (None) 
            3 RETURN_VALUE
>>> dis(g)
2           0 LOAD_CONST               0 (None) 
            3 RETURN_VALUE
...