Puoi usare return
una volta in un generatore; interrompe l'iterazione senza produrre nulla e quindi fornisce un'alternativa esplicita per lasciare che la funzione esca dall'ambito. Quindi usa yield
per trasformare la funzione in un generatore, ma precedilo return
per terminare il generatore prima di cedere qualsiasi cosa.
>>> def f():
... return
... yield
...
>>> list(f())
[]
Non sono sicuro che sia molto meglio di quello che hai - sostituisce semplicemente if
un'istruzione no-op con un'istruzione no-op yield
. Ma è più idiomatico. Nota che il semplice utilizzo yield
non funziona.
>>> def f():
... yield
...
>>> list(f())
[None]
Perché non basta usare iter(())
?
Questa domanda chiede specificamente una funzione di generatore vuoto . Per questo motivo, ritengo che sia una domanda sulla coerenza interna della sintassi di Python, piuttosto che una domanda sul modo migliore per creare un iteratore vuoto in generale.
Se la domanda riguarda effettivamente il modo migliore per creare un iteratore vuoto, potresti essere d'accordo con Zectbumo sull'utilizzo iter(())
. Tuttavia, è importante osservare che iter(())
non restituisce una funzione! Restituisce direttamente un iterabile vuoto. Supponi di lavorare con un'API che si aspetta un chiamabile che restituisce un iterabile. Dovrai fare qualcosa del genere:
def empty():
return iter(())
(Il merito dovrebbe andare a Unutbu per aver fornito la prima versione corretta di questa risposta.)
Ora, potresti trovare quanto sopra più chiaro, ma posso immaginare situazioni in cui sarebbe meno chiaro. Considera questo esempio di un lungo elenco di definizioni di funzioni del generatore (inventate):
def zeros():
while True:
yield 0
def ones():
while True:
yield 1
...
Alla fine di quella lunga lista, preferirei vedere qualcosa con yield
dentro, come questo:
def empty():
return
yield
oppure, in Python 3.3 e versioni successive (come suggerito da DSM ), questo:
def empty():
yield from ()
La presenza della yield
parola chiave fa capire al più breve sguardo che questa è solo un'altra funzione del generatore, esattamente come tutte le altre. Ci vuole un po 'più di tempo per vedere che la iter(())
versione sta facendo la stessa cosa.
È una sottile differenza, ma onestamente penso che le yield
funzioni basate su siano più leggibili e gestibili.
if False: yield
ma ancora un po 'confuso per le persone che non conoscono questo schema