Yeni bir jeneratörü birleştirmek istediğim bir dizi Python jeneratörü var. Bunu, bir grup yield
ifadesini kullanarak elle yazılmış bir jeneratörle kolayca yapabilirim.itertools veya elle yazılmış jeneratör - hangisi tercih edilir?
Diğer taraftan, itertools
modülü, bu gibi şeyler için yapılır ve bana ihtiyacım olan jeneratörü oluşturmanın pythonik yolu, bu itertools
modülünün çeşitli yineleyicileri birbirine bağlamaktır. Bununla birlikte, eldeki problemde, oldukça karmaşık hale gelir (jeneratörün bir tür durumu korumaya ihtiyacı vardır - örneğin, ilk veya daha sonraki öğelerin işlenip işlenmediği ---, i-inci çıktısı daha fazladır.). i-inci giriş öğelerindeki koşullara bağlıdır ve oluşturulan girdi listesine eklenmeden önce çeşitli giriş listeleri farklı şekilde işlenmelidir.
Sorunumu çözecek standart yineleyiciler bileşimi olarak --- nedeniyle kaynak kod aşağı yazma tek boyutlu doğası için --- neredeyse anlaşılmaz, ben elle yazılmış jeneratör fonksiyonları (temel ve daha gelişmiş durumlarda) standart itertools
jeneratörler kullanarak herhangi bir avantaj olup olmadığını merak ediyorum. vakaların% 90’ında ve yazılı versiyonları okumak çok daha kolay --- muhtemelen daha zorlayıcı stilleri nedeniyle zincirleme yineleyicileri işlevsel stili ile karşılaştırıldığında. a
ve b
aynı uzunlukta (giriş verileri) iki Iterables olalım: zaman sorunu göstermek için
DÜZENLEME
, burada (oyuncak) bir örnektir. a
'un öğeleri tam sayılardan oluşur, b
'un öğeleri, tek tek öğeleri dizeleri olan yinelenebilir öğelerdir.
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)
: Ben jeneratör ifadeleri ve
itertools
modülü kullanarak işlevsel bir tarzda aynı programı yazarsan, ben böyle bir şey ile bitirmek
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
: çıktı şu jeneratör fonksiyonunun çıkışına karşılık gelmelidir
Örnek
>>> 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']
Bu bir olası olduğu İlk çözümümden daha zarif bir şekilde daha zariftir, ancak bir keresinde bir kez yazılmamış bir kod parçası gibi görünür. Jeneratörümü yazmanın bu yolunun yapması gereken bir avantajı olup olmadığını merak ediyorum.
Not: Python'daki anahtar kelime miktarını en aza indirgemek için, "for", "if" ve "else" gibi anahtar sözcüklerin, ifadelerde kullanım için geri dönüştürülmüş olduğunu, işlevsel çözümle ilgili sorunumun bir kısmını tahmin ediyorum. Böylece, ifadedeki yerleşimleri alışmaya başlar (z for x in a for y in x for z in y
jeneratör ifadesinde sipariş, en azından bana göre, klasik for
döngüsündeki sıralamaya göre daha az doğal görünür: for x in a: for y in x: for z in y: yield z
).
PS: Ben sadece jeneratör işlevi sopa var öğrendim. Bir şey yapabilir, jeneratör ifadeleriyle yapamam, yani İstisnaları yakalamak. – Marc