Функция Пустого Генератора Python
в python можно легко определить функцию итератора, поместив ключевое слово yield в тело функции, например:
def gen():
for i in range(100):
yield i
как я могу определить функцию генератора, которая не дает никакого значения (генерирует 0 значений), следующий код не работает, так как python не может знать, что он должен быть генератором, а не нормальной функцией:
def empty():
pass
я мог бы сделать что-то вроде
def empty():
if False:
yield None
но это было бы очень некрасиво. Есть ли хороший способ реализовать пустую функцию итератора?
9 ответов:
можно использовать
return
один раз в генераторе; он останавливает итерацию, не давая ничего, и, таким образом, обеспечивает явную альтернативу тому, чтобы позволить функции выйти из области действия. Так что используйтеyield
чтобы превратить функцию в генератор, но предшествовать ему сreturn
чтобы завершить генератор, прежде чем давать что-либо.>>> def f(): ... return ... yield ... >>> list(f()) []
Я не уверен, что это намного лучше, чем то, что у вас есть-он просто заменяет no-op
if
заявление с no-opyield
заявление. Но это больше идиоматический. Обратите внимание, что просто с помощьюyield
не работает.>>> def f(): ... yield ... >>> list(f()) [None]
почему бы просто не использовать
iter(())
?этот вопрос задает конкретно о пустом функции генератора. По этой причине я считаю, что это вопрос о внутренней согласованности синтаксиса Python, а не вопрос о лучшем способе создания пустого итератора в целом.
если вопрос на самом деле о лучшем способе создания пустого итератора, то вы можете согласен с Zectbumo о
iter(())
вместо. Однако важно отметить, чтоiter(())
не возвращает функция! Он непосредственно возвращает пустой iterable. Предположим, вы работаете с API, который ожидает вызываемый that возвращает повторяемое. Вам придется сделать что-то вроде этого:def empty(): return iter(())
(кредит должен идти в Unutbu для предоставления первой правильной версии этого ответа.)
теперь, вы можете найти выше яснее, но я могу представить себе ситуации, в которых это было бы менее ясно. Рассмотрим этот пример длинного списка (надуманных) определений функций генератора:
def zeros(): while True: yield 0 def ones(): while True: yield 1 ...
в конце этого длинного списка, я бы предпочел увидеть что-то с
yield
в нем, как это:def empty(): return yield
или, в Python 3.3 и выше (как было предложено DSM), это:
def empty(): yield from ()
в присутствии
yield
ключевое слово дает понять, на какой взгляд, что это это просто еще одна функция генератора, точно так же, как и все остальные. Это займет немного больше времени, чтобы увидеть, чтоiter(())
версия делает то же самое.это тонкая разница, но я честно думаю, что
yield
функций для более удобного и ремонтопригодны.
Python 3.3 (потому что я на
yield from
удар, а потому @senderle украл мою первую мысль):>>> def f(): ... yield from () ... >>> list(f()) []
но я должен признать, что мне трудно придумать прецедент для этого, для которого
iter([])
или(x)range(0)
не будет работать одинаково хорошо.
Я предпочитаю следующее:
def foo(): raise StopIteration() yield
"выход" превращает его в генератор, а исключение означает, что никто не включен в результат (чисто пустой результат).
"стандартным" способом создания пустого итератора является iter([]). Я предложил сделать [] аргумент по умолчанию для iter(); это было отклонено с хорошими аргументами, см. http://bugs.python.org/issue25215 - Jurjen