Jeneratörler tembel olarak değerlendiriyorlar return
ya yield
da kodunuzda hata ayıklarken veya bir istisna atıldığında farklı davranıyorlar.
İle return
Sepetinde olur herhangi istisna generator
hakkında hiçbir şey bilmeyecek generate_all
ne zaman çünkü bu, generator
gerçekten yürütülür zaten bırakmış generate_all
işlevi. yield
Orada ile geri generate_all
izleme olacak.
def generator(some_list):
for i in some_list:
raise Exception('exception happened :-)')
yield i
def generate_all():
some_list = [1,2,3]
return generator(some_list)
for item in generate_all():
...
Exception Traceback (most recent call last)
<ipython-input-3-b19085eab3e1> in <module>
8 return generator(some_list)
9
---> 10 for item in generate_all():
11 ...
<ipython-input-3-b19085eab3e1> in generator(some_list)
1 def generator(some_list):
2 for i in some_list:
----> 3 raise Exception('exception happened :-)')
4 yield i
5
Exception: exception happened :-)
Ve eğer kullanıyorsa yield from
:
def generate_all():
some_list = [1,2,3]
yield from generator(some_list)
for item in generate_all():
...
Exception Traceback (most recent call last)
<ipython-input-4-be322887df35> in <module>
8 yield from generator(some_list)
9
---> 10 for item in generate_all():
11 ...
<ipython-input-4-be322887df35> in generate_all()
6 def generate_all():
7 some_list = [1,2,3]
----> 8 yield from generator(some_list)
9
10 for item in generate_all():
<ipython-input-4-be322887df35> in generator(some_list)
1 def generator(some_list):
2 for i in some_list:
----> 3 raise Exception('exception happened :-)')
4 yield i
5
Exception: exception happened :-)
Ancak bu, performans maliyetine neden olur. İlave jeneratör katmanının bir miktar ek yükü vardır. Bu yüzden (veya ) return
genellikle biraz daha hızlı olacaktır . Çoğu durumda bu çok önemli olmayacaktır, çünkü jeneratörde ne yaparsanız yapın tipik olarak çalışma zamanına hakim olur, böylece ek katman fark edilmeyecektir.yield from ...
for item in ...: yield item
Bununla birlikte yield
, bazı ek avantajları vardır: Tek bir yinelenebilirle sınırlı değilsiniz, ayrıca kolayca ek öğeler de verebilirsiniz:
def generator(some_list):
for i in some_list:
yield i
def generate_all():
some_list = [1,2,3]
yield 'start'
yield from generator(some_list)
yield 'end'
for item in generate_all():
print(item)
start
1
2
3
end
Sizin durumunuzda işlemler oldukça basittir ve bunun için birden fazla işlev oluşturmanın gerekli olup olmadığını bilmiyorum, biri kolayca dahili map
veya jeneratör ifadesini kullanabilir:
map(do_something, get_the_list()) # map
(do_something(i) for i in get_the_list()) # generator expression
Her ikisi de aynı olmalıdır (istisnalar olduğunda bazı farklılıklar hariç). Ve daha açıklayıcı bir isme ihtiyaçları varsa, onları yine de bir işlevde sarabilirsiniz.
Yerleşik tekrarlanabilirler üzerinde çok yaygın işlemleri saran birden fazla yardımcı vardır ve yerleşik modülde başka işlemler de bulunabilir itertools
. Böyle basit durumlarda sadece bunlara başvururum ve sadece önemsiz durumlar için kendi jeneratörlerinizi yazarım.
Ancak gerçek kodunuzun daha karmaşık olduğunu varsayarım ki bu geçerli olmayabilir, ancak alternatiflerden bahsetmeden bunun tam bir cevap olmayacağını düşündüm.