Jeneratör anlayışı ne işe yarar? O nasıl çalışır? Bununla ilgili bir eğitim bulamadım.
Jeneratör anlayışı ne işe yarar? O nasıl çalışır? Bununla ilgili bir eğitim bulamadım.
Yanıtlar:
Liste anlayışlarını anlıyor musunuz? Eğer öyleyse, bir üreteç ifadesi bir liste anlama gibidir, ancak ilgilendiğiniz tüm öğeleri bulup bunları listelemek yerine bekler ve her öğeyi tek tek ifadeden çıkarır.
>>> my_list = [1, 3, 5, 9, 2, 6]
>>> filtered_list = [item for item in my_list if item > 3]
>>> print(filtered_list)
[5, 9, 6]
>>> len(filtered_list)
3
>>> # compare to generator expression
...
>>> filtered_gen = (item for item in my_list if item > 3)
>>> print(filtered_gen) # notice it's a generator object
<generator object <genexpr> at 0x7f2ad75f89e0>
>>> len(filtered_gen) # So technically, it has no length
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'generator' has no len()
>>> # We extract each item out individually. We'll do it manually first.
...
>>> next(filtered_gen)
5
>>> next(filtered_gen)
9
>>> next(filtered_gen)
6
>>> next(filtered_gen) # Should be all out of items and give an error
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> # Yup, the generator is spent. No values for you!
...
>>> # Let's prove it gives the same results as our list comprehension
...
>>> filtered_gen = (item for item in my_list if item > 3)
>>> gen_to_list = list(filtered_gen)
>>> print(gen_to_list)
[5, 9, 6]
>>> filtered_list == gen_to_list
True
>>>
Bir üretici ifadesinin bir seferde yalnızca bir öğe vermesi gerektiğinden, bellek kullanımında büyük tasarruflara yol açabilir. Üreteç ifadeleri, her seferinde bir öğe almanız, o öğeye göre birçok hesaplama yapmanız ve ardından bir sonraki öğeye geçmeniz gereken senaryolarda en mantıklı olanıdır. Birden fazla değere ihtiyacınız varsa, bir üreteç ifadesi de kullanabilir ve her seferinde birkaçını yakalayabilirsiniz. Programınız ilerlemeden önce tüm değerlere ihtiyacınız varsa, bunun yerine bir liste anlama kullanın.
next(...)yerine her zaman kullanın .__next__().
If you need more than one value, you can also use a generator expression and grab a few at a time. Bu kullanım hakkında bir örnek verebilir misiniz? Teşekkürler.
Liste / oluşturucu kavrama, mevcut bir listeden yeni bir liste / oluşturucu oluşturmak için kullanabileceğiniz bir yapıdır.
Diyelim ki 1'den 10'a kadar her sayının karelerinin listesini oluşturmak istiyorsunuz. Bunu Python'da yapabilirsiniz:
>>> [x**2 for x in range(1,11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
burada range(1,11)listeyi oluşturur [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], ancak rangeişlev Python 3.0'dan önce bir üretici değildir ve bu nedenle kullandığım yapı bir liste anlamadır.
Aynı şeyi yapan bir jeneratör yaratmak isteseydim, şu şekilde yapabilirdim:
>>> (x**2 for x in xrange(1,11))
<generator object at 0x7f0a79273488>
Ancak Python 3'te rangebir oluşturucu olduğundan, sonuç yalnızca kullandığınız söz dizimine bağlıdır (köşeli parantezler veya yuvarlak parantezler).
Jeneratör anlayışı, belirli bir yapıya sahip jeneratörler oluşturmanın kolay bir yoludur. Diyelim generatorki, içindeki tüm çift sayıları birer birer veren bir your_list. İşlev stilini kullanarak oluşturursanız, şu şekilde olur:
def allEvens( L ):
for number in L:
if number % 2 is 0:
yield number
evens = allEvens( yourList )
Bu oluşturucu anlama ifadesi ile aynı sonucu elde edebilirsiniz:
evens = ( number for number in your_list if number % 2 == 0 )
Her iki durumda da, aradığınızda bir next(evens)sonraki çift numarayı alırsınız your_list.
Jeneratör anlayışı, bir kaynak üzerinde hareket eden bir imleç gibi bir şey olan yinelenebilir değerler yaratmak için bir yaklaşımdır. Eğer mysql imlecini veya mongodb imlecini biliyorsanız, tüm gerçek verilerin belleğe bir kerede değil, birer birer yüklendiğinin farkında olabilirsiniz. İmleciniz ileri geri hareket eder, ancak bellekte her zaman bir satır / liste öğesi vardır.
Kısacası, üreteç anlayışını kullanarak python'da kolayca imleçler oluşturabilirsiniz.
Jeneratör anlayışının başka bir örneği:
print 'Generator comprehensions'
def sq_num(n):
for num in (x**2 for x in range(n)):
yield num
for x in sq_num(10):
print x
Oluşturucular yalnızca listelerle aynıdır, küçük fark, listelerde listenin tüm gerekli sayılarını veya öğelerini birlerde almamız, ancak jeneratörlerde gerekli sayıların birer birer verilmesidir. Dolayısıyla, gerekli öğeleri elde etmek için gerekli tüm öğeleri almak için for döngüsünü kullanmalıyız.
#to get all the even numbers in given range
def allevens(n):
for x in range(2,n):
if x%2==0:
yield x
for x in allevens(10)
print(x)
#output
2
4
6
8