Możesz użyć return
raz w generatorze; zatrzymuje iterację bez zwracania niczego, a tym samym zapewnia jawną alternatywę dla pozostawienia funkcji poza zakresem. Użyj więc, yield
aby zamienić funkcję w generator, ale poprzedź ją, return
aby zakończyć generator przed uzyskaniem czegokolwiek.
>>> def f():
... return
... yield
...
>>> list(f())
[]
Nie jestem pewien, czy jest o wiele lepszy niż to, co masz - po prostu zastępuje if
oświadczenie „no-op” yield
oświadczeniem „ no-op” . Ale to jest bardziej idiomatyczne. Zwróć uwagę, że samo użycie yield
nie działa.
>>> def f():
... yield
...
>>> list(f())
[None]
Dlaczego po prostu nie użyć iter(())
?
To pytanie dotyczy konkretnie pustej funkcji generatora . Z tego powodu traktuję to jako pytanie o wewnętrzną spójność składni Pythona, a nie o najlepszy sposób tworzenia pustego iteratora w ogóle.
Jeśli faktycznie pytanie dotyczy najlepszego sposobu utworzenia pustego iteratora, możesz zgodzić się z Zectbumo na użycie iter(())
zamiast tego. Należy jednak zauważyć, że iter(())
nie zwraca funkcji! Bezpośrednio zwraca pustą iterowalną. Załóżmy, że pracujesz z interfejsem API, który oczekuje wywołania, które zwraca iterowalną wartość za każdym razem, gdy jest wywoływana, tak jak zwykła funkcja generatora. Musisz zrobić coś takiego:
def empty():
return iter(())
( Podziękowania należy się Unutbu za podanie pierwszej poprawnej wersji tej odpowiedzi).
Powyższe może być dla ciebie jaśniejsze, ale mogę sobie wyobrazić sytuacje, w których byłoby to mniej jasne. Rozważmy następujący przykład długiej listy (wymyślonych) definicji funkcji generatora:
def zeros():
while True:
yield 0
def ones():
while True:
yield 1
...
Na końcu tej długiej listy wolałbym zobaczyć coś, co zawiera znak yield
, na przykład:
def empty():
return
yield
lub w Pythonie 3.3 i nowszych (zgodnie z sugestią DSM ):
def empty():
yield from ()
Obecność yield
słowa kluczowego sprawia, że na pierwszy rzut oka widać, że jest to tylko kolejna funkcja generatora, dokładnie taka, jak wszystkie inne. Potrzeba trochę więcej czasu, aby zobaczyć, że iter(())
wersja robi to samo.
To subtelna różnica, ale szczerze uważam, że yield
funkcje oparte na systemie są bardziej czytelne i łatwiejsze w utrzymaniu.
Zobacz także tę świetną odpowiedź od użytkownika 3840170, która używa, dis
aby pokazać inny powód, dla którego takie podejście jest lepsze: po kompilacji emituje najmniej instrukcji.
if False: yield
ale wciąż trochę mylące dla ludzi, którzy nie znają tego wzoru