Mam wiele generatorów Python, które chcę połączyć w nowy generator. Mogę to łatwo zrobić za pomocą odręcznego generatora, używając kilku instrukcji: yield
.itertools lub odręczny generator - co jest lepsze?
Z drugiej strony, moduł itertools
jest stworzony dla takich rzeczy i wydaje mi się, że pytonowy sposób tworzenia potrzebnego generatora polega na podłączeniu różnych iteratorów tego modułu itertools
.
Jednak w danym problemie szybko staje się to dość skomplikowane (generator musi utrzymywać pewien stan - np. Czy pierwszy lub późniejszy produkt jest przetwarzany ---, i-te wyjście dalej zależy od warunków na i-tych elementach wejściowych, a różne listy wejściowe muszą być przetwarzane inaczej, zanim zostaną dołączone do wygenerowanej listy:
Ponieważ skład standardowych iteratorów, które rozwiązałyby mój problem, jest następujący: do jednowymiarowego zapisu kodu źródłowego - prawie niezrozumiałe, zastanawiam się, czy istnieją jakiekolwiek zalety używania standardowych generatorów itertools
w porównaniu z ręcznie pisanymi funkcjami generatora (w podstawowych i bardziej zaawansowanych przypadkach). w 90% przypadków h i napisane wersje są znacznie łatwiejsze do odczytania --- prawdopodobnie ze względu na ich bardziej bezwzględny styl w porównaniu do funkcjonalnego stylu łączenia iteratorów.
EDIT
Aby zilustrować mój problem, tu jest (zabawka) Przykład: Niech a
i b
dwa iterables tej samej długości (dane wejściowe). Pozycje a
składają się z liczb całkowitych, elementy z b
są iterables same, których poszczególne elementy są łańcuchami. Wyjście powinno odpowiadać wyjściu następującą funkcję generatora:
from itertools import *
def generator(a, b):
first = True
for i, s in izip(a, b):
if first:
yield "First line"
first = False
else:
yield "Some later line"
if i == 0:
yield "The parameter vanishes."
else:
yield "The parameter is:"
yield i
yield "The strings are:"
comma = False
for t in s:
if comma:
yield ','
else:
comma = True
yield t
Gdybym zanotować ten sam program w stylu funkcjonalnym za pomocą wyrażeń generatora i modułu itertools
, ja skończyć z czymś takim:
from itertools import *
def generator2(a, b):
return (z for i, s, c in izip(a, b, count())
for y in (("First line" if c == 0 else "Some later line",),
("The parameter vanishes.",) if i == 0
else ("The parameter is:", i),
("The strings are:",),
islice((x for t in s for x in (',', t)), 1, None))
for z in y)
Przykład
>>> a = (1, 0, 2), ("ab", "cd", "ef")
>>> print([x for x in generator(a, b)])
['First line', 'The parameter is:', 1, 'The strings are:', 'a', ',', 'b', 'Some later line', 'The parameter vanishes.', 'The strings are:', 'c', ',', 'd', 'Some later line', 'The parameter is:', 2, 'The strings are:', 'e', ',', 'f']
>>> print([x for x in generator2(a, b)])
['First line', 'The parameter is:', 1, 'The strings are:', 'a', ',', 'b', 'Some later line', 'The parameter vanishes.', 'The strings are:', 'c', ',', 'd', 'Some later line', 'The parameter is:', 2, 'The strings are:', 'e', ',', 'f']
to POSS na przykład bardziej elegancko niż moje pierwsze rozwiązanie, ale wygląda na to, że napisałem "nie raz, zrozum, a później". Zastanawiam się, czy ten sposób pisania mojego generatora ma wystarczające zalety, że należy to zrobić.
PS: Domyślam się, że częścią mojego problemu z funkcjonalnym rozwiązaniem jest to, że aby zminimalizować ilość słów kluczowych w Pythonie, niektóre słowa kluczowe, takie jak "dla", "jeśli" i "else" zostały poddane recyklingowi do wykorzystania w wyrażeniach aby ich umieszczenie w wyrażeniu zaczęło się przyzwyczajać (porządek w wyrażeniu generatora z for x in a for y in x for z in y
wygląda, przynajmniej dla mnie, mniej naturalny niż porządek w klasycznej pętli for
: for x in a: for y in x: for z in y: yield z
).
PS: właśnie dowiedziałem się, że mam się trzymać z funkcją generatora. Może zrobić jedną rzecz, nie mogę zrobić z wyrażeń generujących, mianowicie wychwytywaniem wyjątków. – Marc