ÔÇťVerimÔÇŁ anahtar kelimesi ne i┼če yarar?


Al─▒nan cevaba git


yield Anahtar kelimenin Python'da kullan─▒m─▒ nedir ? Bu ne i┼če yar─▒yor?

├ľrne─čin, bu kodu 1 anlamaya ├žal─▒┼č─▒yorum :

 def _get_child_candidates(self, distance, min_dist, max_dist):
    if self._leftchild and distance - max_dist < self._median:
        yield self._leftchild
    if self._rightchild and distance + max_dist >= self._median:
        yield self._rightchild  
 

Ve bu arayan:

 result, candidates = [], [self]
while candidates:
    node = candidates.pop()
    distance = node._get_dist(obj)
    if distance <= max_dist and distance >= min_dist:
        result.extend(node._values)
    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))
return result
 

Y├Ântem _get_child_candidates ├ža─čr─▒ld─▒─č─▒nda ne olur ? Bir liste iade edildi mi? Tek bir element mi? Yine mi arand─▒? Sonraki ├ža─čr─▒lar ne zaman durur?


1. Bu kod par├žas─▒ metrik alanlar i├žin harika bir Python k├╝t├╝phanesi yapan Jochen Schulz (jrschulz) taraf─▒ndan yaz─▒lm─▒┼čt─▒r. Bu, t├╝m kayna─č─▒n ba─člant─▒s─▒d─▒r: Mod├╝l mspace .


9577









Cevap say─▒s─▒n─▒ say: 30






Ne yield yapt─▒─č─▒n─▒ anlamak i├žin, jenerat├Ârlerin ne oldu─čunu anlamal─▒s─▒n─▒z . Ve jenerat├Ârleri anlamadan ├Ânce, yinelemeleri anlamal─▒s─▒n─▒z .

Iterables

Bir liste olu┼čturdu─čunuzda, ├Â─čelerini tek tek okuyabilirsiniz. ├ľ─čelerini birer birer okumak, yineleme olarak adland─▒r─▒l─▒r:

 >>> mylist = [1, 2, 3]
>>> for i in mylist:
...    print(i)
1
2
3
 

mylist bir oldu─čunu iterable . Bir liste kavrama kulland─▒─č─▒n─▒zda, bir liste ve b├Âylece yinelenebilir

 >>> mylist = [x*x for x in range(3)]
>>> for i in mylist:
...    print(i)
0
1
4
 

for... in... ├ťzerinde " " kullanabilece─činiz her ┼čey yinelenebilir; lists ,, strings dosyalar ...

Bu yinelemeler kullan─▒┼čl─▒d─▒r, ├ž├╝nk├╝ bunlar─▒ istedi─činiz kadar okuyabilirsiniz, ancak t├╝m de─čerleri haf─▒zada saklars─▒n─▒z ve bu her zaman istedi─činiz gibi olmaz.

Jenerat├Ârler

Jenerat├Ârler yineleyicilerdir, yaln─▒zca bir defadan fazla yineleyebilece─činiz yinelemelerdir . Jenerat├Ârler t├╝m de─čerleri haf─▒zada tutmazlar, an─▒nda de─čerleri olu┼čtururlar :

 >>> mygenerator = (x*x for x in range(3))
>>> for i in mygenerator:
...    print(i)
0
1
4
 

Sadece senin () yerine kulland─▒─č─▒n d─▒┼č─▒nda ayn─▒ [] . ANCAK, sen olamaz ger├žekle┼čtirmek for i in mygenerator onlar 0 hesaplamak, sonra bunu unutur ve 1 hesaplamak ve teker 4, tek hesaplama sona: jenerat├Ârler sadece kullan─▒labilir beri kez ikinci kez.

Yol ver

yield return i┼člevi bir jenerat├Âr d├Ând├╝recek d─▒┼č─▒nda, gibi kullan─▒lan bir anahtar kelimedir .

 >>> def createGenerator():
...    mylist = range(3)
...    for i in mylist:
...        yield i*i
...
>>> mygenerator = createGenerator() # create a generator
>>> print(mygenerator) # mygenerator is an object!
<generator object createGenerator at 0xb7555c34>
>>> for i in mygenerator:
...     print(i)
0
1
4
 

─░┼čte i┼če yaramaz bir ├Ârnek, ancak i┼člevinizin yaln─▒zca bir kez okuman─▒z gereken b├╝y├╝k bir de─čer k├╝mesi getirece─čini bildi─činizde kullan─▒┼čl─▒d─▒r.

Master i├žin yield , i┼člevi ├ža─č─▒rd─▒─č─▒n─▒zda, i┼člev g├Âvdesine yazd─▒─č─▒n─▒z kodun ├žal─▒┼čmad─▒─č─▒n─▒ anlamal─▒s─▒n─▒z . ─░┼člev yaln─▒zca jenerat├Âr nesnesini d├Ând├╝r├╝r, bu biraz zor :-)

Sonra, kodunuz for jenerat├Âr├╝ her kulland─▒─č─▒nda b─▒rakt─▒─č─▒ yerden devam eder .

┼×imdi zor k─▒sm─▒:

for Fonksiyonunuzdan yarat─▒lan jenerat├Âr nesnesini ilk ├ža─č─▒rd─▒─č─▒nda, fonksiyonunuzdaki kodu ba┼čtan vurmaya ba┼člayana kadar ├žal─▒┼čt─▒r─▒r yield , sonra d├Âng├╝n├╝n ilk de─čerini d├Ând├╝r├╝r. Ard─▒ndan, di─čer aramalar fonksiyona yazd─▒─č─▒n─▒z d├Âng├╝y├╝ bir kez daha ├žal─▒┼čt─▒r─▒r ve d├Ând├╝r├╝lecek de─čer elde edilinceye kadar bir sonraki de─čeri d├Ând├╝r├╝r.

─░┼člev ├žal─▒┼čt─▒ktan sonra jenerat├Âr bo┼č say─▒l─▒r, ancak yield art─▒k ├žarpmaz. Bu, d├Âng├╝n├╝n sona ermesi veya "if/else" art─▒k tatmin etmemeniz olabilir .


Kodunuz a├ž─▒kland─▒

Jenerat├Âr:

 # Here you create the method of the node object that will return the generator
def _get_child_candidates(self, distance, min_dist, max_dist):

    # Here is the code that will be called each time you use the generator object:

    # If there is still a child of the node object on its left
    # AND if the distance is ok, return the next child
    if self._leftchild and distance - max_dist < self._median:
        yield self._leftchild

    # If there is still a child of the node object on its right
    # AND if the distance is ok, return the next child
    if self._rightchild and distance + max_dist >= self._median:
        yield self._rightchild

    # If the function arrives here, the generator will be considered empty
    # there is no more than two values: the left and the right children
 

Arayan:

 # Create an empty list and a list with the current object reference
result, candidates = list(), [self]

# Loop on candidates (they contain only one element at the beginning)
while candidates:

    # Get the last candidate and remove it from the list
    node = candidates.pop()

    # Get the distance between obj and the candidate
    distance = node._get_dist(obj)

    # If distance is ok, then you can fill the result
    if distance <= max_dist and distance >= min_dist:
        result.extend(node._values)

    # Add the children of the candidate in the candidate's list
    # so the loop will keep running until it will have looked
    # at all the children of the children of the children, etc. of the candidate
    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))

return result
 

Bu kod birka├ž ak─▒ll─▒ par├ža i├žerir:

  • D├Âng├╝ bir listede yinelenir, ancak d├Âng├╝ yinelenirken liste geni┼čler :-) Sonsuz bir d├Âng├╝ye sahip olabilece─činizden, biraz tehlikeli olsa bile bu i├ž i├že ge├žmi┼č t├╝m verileri g├Âzden ge├žirmenin ├Âzl├╝ bir yoludur. Bu durumda, candidates.extend(node._get_child_candidates(distance, min_dist, max_dist)) jenerat├Âr├╝n t├╝m de─čerlerini t├╝ketin, ancak while ayn─▒ d├╝─č├╝mde uygulanmad─▒─č─▒ndan ├Ânceki de─čerlerden farkl─▒ de─čerler ├╝retecek yeni jenerat├Âr nesneleri olu┼čturmaya devam eder.

  • extend() Y├Ântem, bir iterable bekler ve listeye de─čerlerini ekleyen bir liste nesnesinin bir y├Ântemdir.

Genellikle bir liste ├ž─▒kar─▒r─▒z:

 >>> a = [1, 2]
>>> b = [3, 4]
>>> a.extend(b)
>>> print(a)
[1, 2, 3, 4]
 

Ancak kodunuzda, bir jenerat├Âr al─▒r, ki bu iyi ├ž├╝nk├╝:

  1. De─čerleri iki kez okuman─▒za gerek yok.
  2. ├çok fazla ├žocu─čunuz olabilir ve hepsinin bellekte saklanmas─▒n─▒ istemiyorsunuz.

Ve i┼če yar─▒yor ├ž├╝nk├╝ Python bir y├Ântemin arg├╝man─▒n─▒n bir liste olup olmad─▒─č─▒na ald─▒rm─▒yor. Python yinelemeler bekler, b├Âylece dizelerle, listelerle, totelerle ve jenerat├Ârler ile ├žal─▒┼čacakt─▒r! Buna ├Ârdek yazmas─▒ denir ve Python'un bu kadar iyi olmas─▒n─▒n sebeplerinden biridir. Ama bu ba┼čka bir hikaye, ba┼čka bir soru i├žin ...

Bir jenerat├Âr├╝n geli┼čmi┼č kullan─▒m─▒n─▒ g├Ârmek i├žin burada durabilir veya biraz okuyabilirsiniz:

Jenerat├Âr yorgunlu─čunu kontrol etme

 >>> class Bank(): # Let's create a bank, building ATMs
...    crisis = False
...    def create_atm(self):
...        while not self.crisis:
...            yield "$100"
>>> hsbc = Bank() # When everything's ok the ATM gives you as much as you want
>>> corner_street_atm = hsbc.create_atm()
>>> print(corner_street_atm.next())
$100
>>> print(corner_street_atm.next())
$100
>>> print([corner_street_atm.next() for cash in range(5)])
['$100', '$100', '$100', '$100', '$100']
>>> hsbc.crisis = True # Crisis is coming, no more money!
>>> print(corner_street_atm.next())
<type 'exceptions.StopIteration'>
>>> wall_street_atm = hsbc.create_atm() # It's even true for new ATMs
>>> print(wall_street_atm.next())
<type 'exceptions.StopIteration'>
>>> hsbc.crisis = False # The trouble is, even post-crisis the ATM remains empty
>>> print(corner_street_atm.next())
<type 'exceptions.StopIteration'>
>>> brand_new_atm = hsbc.create_atm() # Build a new one to get back in business
>>> for cash in brand_new_atm:
...    print cash
$100
$100
$100
$100
$100
$100
$100
$100
$100
...
 

Not: Python 3 i├žin, print(corner_street_atm.__next__()) veya print(next(corner_street_atm))

Bir kayna─ča eri┼čimi kontrol etmek gibi ├že┼čitli ┼čeyler i├žin faydal─▒ olabilir.

─░tertools, en iyi arkada┼č─▒n

─░tertools mod├╝l├╝, tekrarlanabilirleri i┼člemek i├žin ├Âzel fonksiyonlar i├žerir. Hi├ž bir jenerat├Âr├╝ ├žo─čaltmak istediniz mi? Zincir iki jenerat├Âr? Tek astarl─▒ i├ž i├že bir listede grup de─čerleri? Map / Zip ba┼čka bir liste olu┼čturmadan?

O zaman sadece import itertools .

Bir ├Ârnek? D├Ârt atl─▒ bir yar─▒┼č i├žin olas─▒ var─▒┼č talimatlar─▒n─▒ g├Ârelim:

 >>> horses = [1, 2, 3, 4]
>>> races = itertools.permutations(horses)
>>> print(races)
<itertools.permutations object at 0xb754f1dc>
>>> print(list(itertools.permutations(horses)))
[(1, 2, 3, 4),
 (1, 2, 4, 3),
 (1, 3, 2, 4),
 (1, 3, 4, 2),
 (1, 4, 2, 3),
 (1, 4, 3, 2),
 (2, 1, 3, 4),
 (2, 1, 4, 3),
 (2, 3, 1, 4),
 (2, 3, 4, 1),
 (2, 4, 1, 3),
 (2, 4, 3, 1),
 (3, 1, 2, 4),
 (3, 1, 4, 2),
 (3, 2, 1, 4),
 (3, 2, 4, 1),
 (3, 4, 1, 2),
 (3, 4, 2, 1),
 (4, 1, 2, 3),
 (4, 1, 3, 2),
 (4, 2, 1, 3),
 (4, 2, 3, 1),
 (4, 3, 1, 2),
 (4, 3, 2, 1)]
 

Yinelemenin i├ž mekanizmalar─▒n─▒ anlama

Yineleme yinelemeleri ( __iter__() y├Ântemi uygulayan ) ve yineleyicileri ( __next__() y├Ântemi uygulayan) i├žeren bir i┼člemdir . Yinelemeler, yineleyiciyi alabilece─činiz nesnelerdir. Yineleyiciler yinelemeler ├╝zerinde yinelemenizi sa─člayan nesnelerdir.

D├Âng├╝lerin nas─▒l for ├žal─▒┼čt─▒─č─▒ hakk─▒nda bu makalede daha fazlas─▒ var .


13866







Anlama k─▒sayolu yield

yield ─░fadelere sahip bir i┼člev g├Ârd├╝─č├╝n├╝zde , ne olaca─č─▒n─▒ anlamak i├žin bu kolay numaray─▒ uygulay─▒n:

  1. result = [] Fonksiyonun ba┼č─▒na bir sat─▒r ekleyin .
  2. Her de─či┼čtirin yield expr ile result.append(expr) .
  3. return result Fonksiyonun alt─▒na bir sat─▒r ekleyin .
  4. Yay - daha fazla yield a├ž─▒klama yok ! Kodu oku ve ├ž├Âz.
  5. Fonksiyonu orijinal tan─▒mla kar┼č─▒la┼čt─▒r─▒n.

Bu numara size i┼člevin ard─▒ndaki mant─▒k hakk─▒nda bir fikir verebilir, ancak ger├žekte olan ┼čey yield , listeye dayal─▒ yakla┼č─▒mda olanlardan ├Ânemli ├Âl├ž├╝de farkl─▒d─▒r. ├ço─ču durumda, verim yakla┼č─▒m─▒ ├žok daha fazla bellek verimli ve daha h─▒zl─▒ olacakt─▒r. Di─čer durumlarda, bu numara, orijinal i┼člev d├╝zg├╝n ├žal─▒┼čsa bile sizi sonsuz bir d├Âng├╝ye sokar. Daha fazlas─▒n─▒ ├Â─črenmek i├žin okumaya devam edin ...

Yineleyiciler, yineleyiciler ve jenerat├Ârler kar─▒┼čt─▒rmay─▒n

─░lk ├Ânce, yineleyici protokol├╝ - yazarken

 for x in mylist:
    ...loop body...
 

Python a┼ča─č─▒daki iki ad─▒m─▒ ger├žekle┼čtirir:

  1. Bir yineleyici i├žin al─▒r mylist :

    Call iter(mylist) -> bu, bir next() y├Ântemle (veya __next__() Python 3'te) bir nesne d├Ând├╝r├╝r .

    [Bu, ├žo─ču insan─▒n size anlatmay─▒ unuttu─ču ad─▒md─▒r]

  2. ├ľ─čeler ├╝zerinde d├Âng├╝ olu┼čturmak i├žin yineleyiciyi kullan─▒r:

    Aramaya devam next() Ad─▒m 1. d├Ân├╝┼č de─čeri d├Ânen yineleyici y├Ântemini next() atan─▒r x ve halka g├Âvdesi y├╝r├╝t├╝l├╝r. Bir istisna StopIteration i├žeriden y├╝kseltilirse next() , yineleyicide daha fazla de─čer olmad─▒─č─▒ ve d├Âng├╝den ├ž─▒k─▒ld─▒─č─▒ anlam─▒na gelir.

Ger├žek ┼ču ki Python , bir nesnenin i├žeri─či ├╝zerinde d├Âng├╝ yapmak istedi─či zaman yukar─▒daki iki ad─▒m─▒ ger├žekle┼čtirir - bu bir for d├Âng├╝s├╝ olabilir, fakat ayn─▒ zamanda otherlist.extend(mylist) ( otherlist Python listesi) gibi bir kod da olabilir .

─░┼čte mylist bir oldu─čunu iterable o yineleyici protokol├╝n├╝ uygulayan ├ž├╝nk├╝. Kullan─▒c─▒ tan─▒ml─▒ bir s─▒n─▒fta, s─▒n─▒f─▒n─▒z─▒n __iter__() ├Ârneklerini yinelenebilir hale getirmek i├žin y├Ântemi uygulayabilirsiniz. Bu y├Ântem bir yineleyici d├Ând├╝rmelidir . Bir yineleyici, next() y├Ântemi olan bir nesnedir . Hem uygulamak m├╝mk├╝nd├╝r __iter__() ve next() ayn─▒ s─▒n─▒f─▒na ve sahip __iter__() d├Ân├╝┼č├╝ self . Bu basit durumlar i├žin i┼če yarayacakt─▒r, ancak iki yineleyicinin ayn─▒ nesnenin ├╝zerinde ayn─▒ anda d├Âng├╝ yapmas─▒n─▒ istemiyorsan─▒z.

Yani yineleme protokol├╝, bir├žok nesne bu protokol├╝ uygular:

  1. Yerle┼čik listeler, s├Âzl├╝kler, dosyalar, k├╝meler, dosyalar.
  2. Uygulayan kullan─▒c─▒ tan─▒ml─▒ s─▒n─▒flar __iter__() .
  3. Jenerat├Ârler.

Bir for d├Âng├╝n├╝n ne t├╝r bir nesne ile u─čra┼čt─▒─č─▒n─▒ bilmedi─čine dikkat edin - yaln─▒zca yineleyici protokol├╝n├╝ izler ve ├Â─čeden sonra ├Â─čeyi ├ža─č─▒r─▒rken mutlu olur next() . Dahili listeleri iade onlar─▒n ├╝r├╝n birini teker, s├Âzl├╝kler d├Ânmek tu┼člar─▒ teker teker dosyalar─▒ iade hatlar─▒ en iyi nerede oldu─čunu ... vs teker teker Ve jenerat├Ârler d├Ânmek yield gelir:

 def f123():
    yield 1
    yield 2
    yield 3

for item in f123():
    print item
 

Yerine yield ifadeleri ├╝├ž olsayd─▒, return ifadeleri f123() sadece ilk ├žal─▒┼čt─▒r─▒lamazd─▒ ve i┼člev ├ž─▒kmak istiyorum. Ancak f123() s─▒radan bir i┼člev de─čildir. Ne zaman f123() denir, bu olmaz verim tablolara de─čerlerden herhangi birini d├Ân├╝┼č! Bir jenerat├Âr nesnesini d├Ând├╝r├╝r. Ayr─▒ca, i┼člev ger├žekten ├ž─▒km─▒yor - ask─▒ya al─▒nm─▒┼č bir duruma ge├žiyor. Ne zaman for d├Âng├╝ jenerat├Âr nesnenin ├╝zerine d├Âng├╝ ├žal─▒┼č─▒r, fonksiyon sonra ertesi ├žizgisinde as─▒l─▒ konumundan itibaren devam eder yield , daha ├Ânce d├Ânen bu durumda, bir sonraki kod sat─▒r─▒n─▒ y├╝r├╝t├╝r yield deyimi, ve iadeler sonraki ├Â─če olarak . Bu, fonksiyon ├ž─▒k─▒ncaya kadar, jenerat├Âr├╝n hangi noktada y├╝kseldi─čini StopIteration ve d├Âng├╝ ├ž─▒k─▒ncaya kadar olur .

Yani jenerat├Âr nesne s─▒ralama bir adapt├Âr gibi biridir - bu te┼čhir ederek, yineleyici protokol├╝n├╝ sergileyen bir ucunda __iter__() ve next() tutmak i├žin y├Ântemler for d├Âng├╝ mutlu. Bununla birlikte, di─čer ucunda, bir sonraki de─čeri elde etmek i├žin i┼člevi yeterince ├žal─▒┼čt─▒r─▒r ve ask─▒ya alma moduna geri d├Ând├╝r├╝r.

Neden Jenerat├Âr Kullanmal─▒?

Genellikle, jenerat├Âr kullanmayan ancak ayn─▒ mant─▒─č─▒ uygulayan kod yazabilirsiniz. Bir se├ženek daha ├Ânce bahsetti─čim ge├žici liste 'hile' kullanmakt─▒r. Bu, her durumda i┼če yaramayacakt─▒r, ├Ârne─čin sonsuz d├Âng├╝leriniz varsa veya ├žok uzun bir listeniz oldu─čunda haf─▒zay─▒ verimsiz kullanabilir. Di─čer bir yakla┼č─▒m, SomethingIter ├Ârnek ├╝yelerdeki durumu koruyan ve bir sonraki mant─▒ksal ad─▒m─▒ next() (veya __next__() Python 3) y├Ânteminde ger├žekle┼čtiren yinelemeli bir s─▒n─▒f uygulamakt─▒r . Mant─▒─ča ba─čl─▒ olarak, next() y├Ântemin i├žindeki kod ├žok karma┼č─▒k g├Âr├╝nebilir ve hatalara a├ž─▒k olabilir. Burada jenerat├Ârler temiz ve kolay bir ├ž├Âz├╝m sunar.


1874







Bu ┼čekilde d├╝┼č├╝n:

Bir yineleyici, bir next() metodu olan bir cisim i├žin sadece ┼č─▒k bir seslendirme terimidir . B├Âylece verim kazanm─▒┼č bir i┼člev ┼č├Âyle olur:

Orijinal versiyon:

 def some_function():
    for i in xrange(4):
        yield i

for i in some_function():
    print i
 

Bu temelde Python yorumlay─▒c─▒s─▒n─▒n yukar─▒daki kodla yapt─▒─č─▒ ┼čeydir:

 class it:
    def __init__(self):
        # Start at -1 so that we get 0 when we add 1 below.
        self.count = -1

    # The __iter__ method will be called once by the 'for' loop.
    # The rest of the magic happens on the object returned by this method.
    # In this case it is the object itself.
    def __iter__(self):
        return self

    # The next method will be called repeatedly by the 'for' loop
    # until it raises StopIteration.
    def next(self):
        self.count += 1
        if self.count < 4:
            return self.count
        else:
            # A StopIteration exception is raised
            # to signal that the iterator is done.
            # This is caught implicitly by the 'for' loop.
            raise StopIteration

def some_func():
    return it()

for i in some_func():
    print i
 

Sahne arkas─▒nda neler olup bitti─čiyle ilgili daha fazla bilgi edinmek i├žin, for d├Âng├╝ ┼ču ┼čekilde yeniden yaz─▒labilir:

 iterator = some_func()
try:
    while 1:
        print iterator.next()
except StopIteration:
    pass
 

Bu daha mant─▒kl─▒ m─▒ yoksa sadece seni daha fazla m─▒ kar─▒┼čt─▒r─▒yor? :)

Bu unutmamal─▒d─▒r olan g├Âsterim ama├žl─▒ bir basitle┼čtirme. :)


504







yield Anahtar kelime iki basit ger├žekleri indirgenir:

  1. Derleyici bir i┼člevi i├žinde herhangi bir yerde yield anahtar kelimeyi alg─▒larsa , bu i┼člev art─▒k ifade arac─▒l─▒─č─▒yla geri d├Ânmez . Bunun yerine , derhal bir jenerat├Âr adl─▒ tembel bir "bekleyen liste" nesnesini d├Ând├╝r├╝r return
  2. Bir jenerat├Âr yinelenebilir. Bir nedir iterable ? Her bir ├Â─čeyi belirli bir s─▒rayla ziyaret etmek i├žin yerle┼čik bir protokol i├žeren, list veya set veya range veya dikt-view gibi bir ┼čey .

├ľzet olarak: bir jenerat├Âr tembel, ad─▒m ad─▒m beklemede olan bir listedir ve yield ifadeler , jenerat├Âr├╝n artan ┼čekilde t├╝k├╝rmesi gereken liste de─čerlerini programlamak i├žin i┼člev g├Âsterimini kullanman─▒za izin verir .

 generator = myYieldingFunction(...)
x = list(generator)

   generator
       v
[x[0], ..., ???]

         generator
             v
[x[0], x[1], ..., ???]

               generator
                   v
[x[0], x[1], x[2], ..., ???]

                       StopIteration exception
[x[0], x[1], x[2]]     done

list==[x[0], x[1], x[2]]
 

├ľrnek

makeRange Python'unki gibi bir i┼člev tan─▒mlayal─▒m range . Arayan makeRange(n) bir JENERAT├ľR d├Ând├╝r├╝r:

 def makeRange(n):
    # return 0,1,2,...,n-1
    i = 0
    while i < n:
        yield i
        i += 1

>>> makeRange(5)
<generator object makeRange at 0x19e4aa0>
 

Jenerat├Âr├╝ beklemedeki de─čerlerini derhal geri g├Ândermeye zorlamak i├žin, i├žine aktarabilirsiniz list() (t─▒pk─▒ yinelendirebilece─činiz gibi):

 >>> list(makeRange(5))
[0, 1, 2, 3, 4]
 

"Sadece bir liste d├Ând├╝rmek" ├Ârne─čiyle kar┼č─▒la┼čt─▒rmak

Yukar─▒daki ├Ârnekte sadece ekledi─činiz ve iade etti─činiz bir liste olu┼čturdu─ču d├╝┼č├╝n├╝lebilir:

 # list-version                   #  # generator-version
def makeRange(n):                #  def makeRange(n):
    """return [0,1,2,...,n-1]""" #~     """return 0,1,2,...,n-1"""
    TO_RETURN = []               #>
    i = 0                        #      i = 0
    while i < n:                 #      while i < n:
        TO_RETURN += [i]         #~         yield i
        i += 1                   #          i += 1  ## indented
    return TO_RETURN             #>

>>> makeRange(5)
[0, 1, 2, 3, 4]
 

Yine de b├╝y├╝k bir fark var; son b├Âl├╝me bak─▒n─▒z.


Jenerat├Ârleri nas─▒l kullanabilirsiniz?

Yinelenebilir bir listenin kavranmas─▒n─▒n son k─▒sm─▒d─▒r ve t├╝m ├╝rete├žler yinelenebilir, bu y├╝zden s─▒kl─▒kla ┼č├Âyle kullan─▒l─▒rlar:

 #                   _ITERABLE_
>>> [x+10 for x in makeRange(5)]
[10, 11, 12, 13, 14]
 

Jenerat├Ârler i├žin daha iyi hissetmek i├žin, itertools mod├╝lle oynayabilirsiniz ( garanti edilmek chain.from_iterable yerine kullanmaktan emin olun chain ). ├ľrne─čin, sonsuz uzun tembel listeler gibi uygulamak i├žin jenerat├Ârleri bile kullanabilirsiniz itertools.count() . Kendinizi uygulayabilir def enumerate(iterable): zip(count(), iterable) veya alternatif yield olarak bir while d├Âng├╝s├╝ i├žinde anahtar kelimeyle bunu yapabilirsiniz .

L├╝tfen dikkat: jenerat├Ârler asl─▒nda koroinler uygulamak veya deterministik olmayan programlama veya di─čer zarif ┼čeyler yapmak i├žin daha bir├žok ┼čey i├žin kullan─▒labilir . Ancak, burada sunulan "tembel listeler" bak─▒┼č a├ž─▒s─▒ bulabilece─činiz en yayg─▒n kullan─▒md─▒r.


Kamera ARKASI

"Python yineleme protokol├╝" bu ┼čekilde ├žal─▒┼č─▒r. Yani, ne zaman oluyor oluyor list(makeRange(5)) . Bu daha ├Ânce "tembel, artan bir liste" olarak tan─▒mlad─▒─č─▒m ┼čey.

 >>> x=iter(range(5))
>>> next(x)
0
>>> next(x)
1
>>> next(x)
2
>>> next(x)
3
>>> next(x)
4
>>> next(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
 

Dahili fonksiyonu next() sadece nesnelerin ├ža─č─▒ran .next() "yineleme protokol├╝" bir par├žas─▒d─▒r ve t├╝m yineleyiciler bulunur i┼člevi. next() Fantezi ┼čeyleri (genellikle okunabilirlik pahas─▒na) uygulamak i├žin i┼člevi (ve yineleme protokol├╝n├╝n di─čer b├Âl├╝mlerini) el ile kullanabilirsiniz , bu y├╝zden bunu yapmaktan ka├ž─▒n─▒n ...


├ľnemsiz ayr─▒nt─▒lar

Normalde, ├žo─ču insan a┼ča─č─▒daki farkl─▒l─▒klar─▒ ├Ânemsemez ve muhtemelen burada okumay─▒ b─▒rakmak ister.

Python-speak, yinelenebilir bir liste gibi bir "d├Âng├╝ formas─▒ kavram─▒n─▒ anlayan" herhangi bir nesnedir [1,2,3] ve yineleyici istenen for d├Âng├╝s├╝ i├žin belirli bir ├Ârne─čidir [1,2,3].__iter__() . Bir jenerat├Âr , yaz─▒lma ┼čekli d─▒┼č─▒nda (fonksiyon s├Âzdizimi ile), herhangi bir yineleyici ile tamamen ayn─▒d─▒r.

Bir listeden bir yineleyici istedi─činde, yeni bir yineleyici olu┼čturur. Bununla birlikte, bir yineleyiciden (nadiren yapaca─č─▒n─▒z) bir yineleyici iste─činde bulundu─čunuzda, yaln─▒zca kendi kopyas─▒n─▒ verir.

B├Âylece, olas─▒ bir olayda b├Âyle bir ┼čey yapamaman─▒z ...

 > x = myRange(5)
> list(x)
[0, 1, 2, 3, 4]
> list(x)
[]
 

... o zaman bir jenerat├Âr├╝n bir yineleyici oldu─čunu unutmay─▒n ; yani, bir kerelik kullan─▒md─▒r. Tekrar kullanmak istiyorsan myRange(...) tekrar aramal─▒s─▒n . Sonucu iki kez kullanman─▒z gerekirse, sonucu bir listeye d├Ân├╝┼čt├╝r├╝n ve de─či┼čkende saklay─▒n x = list(myRange(5)) . Bir jenerat├Âr├╝ kesinlikle klonlamaya ihtiya├ž duyanlar (├Ârne─čin, korkutucu derecede meta metagramlamay─▒ yapanlar), itertools.tee kesinlikle gerekliyse kullanabilirler , ├ž├╝nk├╝ yinelenebilir Python PEP standartlar─▒ ├Ânerisi ertelenmi┼čtir.


420







yield Anahtar kelime Python'da ne yapar ?

Cevap Anahat / ├ľzet

  • ─░le bir i┼člev yield olarak adland─▒r─▒lan, bir d├Âner Generator .
  • Jenerat├Ârler yineleyicilerdir, ├ž├╝nk├╝ yineleyici protokol├╝n├╝ uygularlar , b├Âylece bunlar─▒n ├╝zerinde yineleme yapabilirsiniz.
  • Bir jenerat├Âre ayr─▒ca bilgi g├Ânderilebilir ve bu da kavramsal olarak bir coroutine d├Ân├╝┼č├╝r .
  • Python 3'te, her iki y├Ânde bir jenerat├Ârden di─čerine yetki verebilirsiniz yield from .
  • (Ek, birincisi de dahil olmak ├╝zere birka├ž yan─▒t─▒ ele┼čtirir ve return jenerat├Âr├╝n kullan─▒m─▒n─▒ tart─▒┼č─▒r .)

Jenerat├Ârler:

yield bir fonksiyon tan─▒mlamas─▒nda sadece yasald─▒r ve bir fonksiyon tan─▒m─▒na dahil edilmesi yield onu bir jenerat├Âr d├Ând├╝r├╝r.

Jenerat├Ârler i├žin fikir, farkl─▒ uygulamalara sahip di─čer dillerden (bkz. Dipnot 1). Python'un Jenerat├Ârlerinde, kodun ├žal─▒┼čmas─▒ verim noktas─▒nda dondurulur . Jenerat├Âr ├ža─čr─▒ld─▒─č─▒nda (y├Ântemler a┼ča─č─▒da tart─▒┼č─▒lm─▒┼čt─▒r), y├╝r├╝tme devam eder ve bir sonraki verimle donar.

yield A┼ča─č─▒daki iki y├Ântemle tan─▒mlanan yineleyici protokol├╝n├╝ uygulaman─▒n kolay bir yolunu sa─člar : __iter__ ve next (Python 2) veya __next__ (Python 3). Bu y├Ântemlerin her ikisi de, bir nesneyi mod├╝lden Iterator ├ľzet Taban S─▒n─▒f─▒ ile yazabilece─činiz bir yineleyici yapar collections .

 >>> def func():
...     yield 'I am'
...     yield 'a generator!'
... 
>>> type(func)                 # A function with yield is still a function
<type 'function'>
>>> gen = func()
>>> type(gen)                  # but it returns a generator
<type 'generator'>
>>> hasattr(gen, '__iter__')   # that's an iterable
True
>>> hasattr(gen, 'next')       # and with .next (.__next__ in Python 3)
True                           # implements the iterator protocol.
 

Jenerat├Âr t├╝r├╝ bir yineleyicinin alt t├╝r├╝d├╝r:

 >>> import collections, types
>>> issubclass(types.GeneratorType, collections.Iterator)
True
 

Ve gerekirse, ┼č├Âyle yazabiliriz:

 >>> isinstance(gen, types.GeneratorType)
True
>>> isinstance(gen, collections.Iterator)
True
 

Bir ├Âzelli─či, bir Iterator kez t├╝kendi─činde tekrar kullanamaz veya s─▒f─▒rlayamazs─▒n─▒z:

 >>> list(gen)
['I am', 'a generator!']
>>> list(gen)
[]
 

─░┼člevselli─čini tekrar kullanmak istiyorsan─▒z ba┼čka bir tane daha yapman─▒z gerekecek (bkz. Dipnot 2):

 >>> list(func())
['I am', 'a generator!']
 

Bir ki┼či programl─▒ olarak veri ├╝retebilir, ├Ârne─čin:

 def func(an_iterable):
    for item in an_iterable:
        yield item
 

Yukar─▒daki basit jenerat├Âr ayn─▒ zamanda a┼ča─č─▒dakine de e┼čittir - Python 3.3'ten itibaren (ve Python 2'de bulunmaz), ┼čunlar─▒ kullanabilirsiniz yield from :

 def func(an_iterable):
    yield from an_iterable
 

Bununla birlikte, yield from alt ko-rutinlerle i┼čbirli─či yapan delegasyonla ilgili bir sonraki b├Âl├╝mde a├ž─▒klanacak olan alt jenerat├Ârlere delegasyon yap─▒lmas─▒na da izin verilir.

E┼čyordamlar:

yield Verilerin jenerat├Âre g├Ânderilmesine izin veren bir ifade olu┼čturur (bkz. dipnot 3)

├ľrnek received olarak, jenerat├Âre g├Ânderilen verilere i┼čaret edecek de─či┼čkeni not edin :

 def bank_account(deposited, interest_rate):
    while True:
        calculated_interest = interest_rate * deposited 
        received = yield calculated_interest
        if received:
            deposited += received


>>> my_account = bank_account(1000, .05)
 

─░lk ├Ânce, jenerat├Âr├╝ yerle┼čik i┼člevi ile s─▒raya almal─▒y─▒z next . Kullanmakta oldu─čunuz Python s├╝r├╝m├╝ne ba─čl─▒ olarak uygun y├Ântemi next veya __next__ y├Ântemi arayacakt─▒r :

 >>> first_year_interest = next(my_account)
>>> first_year_interest
50.0
 

Ve ┼čimdi jenerat├Âre veri g├Ânderebiliriz. ( G├Ânderme None , arama yapmakla ayn─▒d─▒r next .):

 >>> next_year_interest = my_account.send(first_year_interest + 1000)
>>> next_year_interest
102.5
 

Alt Koroutine ─░┼čbirli─či Heyeti ile yield from

┼×imdi, yield from Python 3'te mevcut olanlar─▒ hat─▒rlay─▒n . Bu, coroutinler'i bir alt coutine devretmemize izin verir:

 def money_manager(expected_rate):
    under_management = yield     # must receive deposited value
    while True:
        try:
            additional_investment = yield expected_rate * under_management 
            if additional_investment:
                under_management += additional_investment
        except GeneratorExit:
            '''TODO: write function to send unclaimed funds to state'''
        finally:
            '''TODO: write function to mail tax info to client'''


def investment_account(deposited, manager):
    '''very simple model of an investment account that delegates to a manager'''
    next(manager) # must queue up manager
    manager.send(deposited)
    while True:
        try:
            yield from manager
        except GeneratorExit:
            return manager.close()
 

Ve ┼čimdi i┼člevselli─či bir alt jenerat├Âre devredebiliriz ve bir jenerat├Âr taraf─▒ndan yukar─▒daki gibi kullan─▒labilir:

 >>> my_manager = money_manager(.06)
>>> my_account = investment_account(1000, my_manager)
>>> first_year_return = next(my_account)
>>> first_year_return
60.0
>>> next_year_return = my_account.send(first_year_return + 1000)
>>> next_year_return
123.6
 

Sen kesin semantik hakk─▒nda daha fazla bilgi bulabilirsiniz yield from i├žinde PEP 380.

Di─čer Y├Ântemler: yak─▒n ve at

close Y├Ântem y├╝kseltir GeneratorExit fonksiyonu y├╝r├╝tme dondurulmu┼č noktada. Bu ayn─▒ zamanda ┼č├Âyle ├ža─č─▒r─▒lacakt─▒r, __del__ b├Âylece herhangi bir temizleme kodunu a┼ča─č─▒dakileri kullanaca─č─▒n─▒z yere koyabilirsiniz GeneratorExit :

 >>> my_account.close()
 

Ayr─▒ca, jenerat├Ârde i┼členebilecek veya kullan─▒c─▒ya geri iletilebilecek bir istisna da atabilirsiniz:

 >>> import sys
>>> try:
...     raise ValueError
... except:
...     my_manager.throw(*sys.exc_info())
... 
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
  File "<stdin>", line 2, in <module>
ValueError
 

Sonu├ž

A┼ča─č─▒daki sorunun t├╝m y├Ânlerini ele ald─▒─č─▒m─▒ d├╝┼č├╝n├╝yorum:

yield Anahtar kelime Python'da ne yapar ?

├çok yield ┼čey oldu─ču ortaya ├ž─▒kt─▒ . Bundan daha ayr─▒nt─▒l─▒ ├Ârnekler ekleyebilece─čime eminim. Daha fazla istiyorsan veya yap─▒c─▒ bir ele┼čtirin varsa, bana yorum yazarak bildir.


Ek:

Ba┼čl─▒ca / Kabul Edilen Cevab─▒n Ele┼čtirisi **

  • ├ľrnek olarak sadece bir listeyi kullanarak, yinelenebilir k─▒lan ├╝zerine ┼ča┼č─▒r─▒yor . Yukar─▒daki referanslar─▒ma bak─▒n, fakat ├Âzet olarak: bir yinelemenin yineleyiciyi __iter__ d├Ând├╝ren bir y├Ântemi vard─▒r . Bir yineleyici , y├╝kseltene kadar d├Âng├╝ler taraf─▒ndan dolayl─▒ olarak adland─▒r─▒lan bir (Python 2 veya (Python 3) y├Ântemi sa─člar ve bir kez bunu yapmaya devam eder. .next .__next__ for StopIteration
  • Daha sonra bir jenerat├Âr├╝n ne oldu─čunu a├ž─▒klamak i├žin bir jenerat├Âr ifadesi kullan─▒r. Bir jenerat├Âr sadece bir yineleyici olu┼čturmak i├žin uygun bir yol oldu─ču i├žin , sadece konuyu kar─▒┼čt─▒r─▒r ve biz hala yield k─▒sma gelmedik .
  • Gelen bir jenerat├Âr yorgunluk Kontrol o arad─▒─č─▒nda .next yerine o yerle┼čik i┼člevi kullanmak gerekirken, y├Ântem, next . Uygun bir dolayl─▒ katman─▒ olacakt─▒r, ├ž├╝nk├╝ kodu Python 3'te ├žal─▒┼čmaz.
  • Itertools? Bu hi├žbir ┼čeyle alakal─▒ de─čildi yield .
  • Python 3'teki yield yeni i┼člevsellik ile birlikte sunulan y├Ântemlerin tart─▒┼č─▒lmas─▒. En ├╝stte / kabul edilen cevap ├žok eksik bir cevapt─▒r. yield from

yield Bir ├╝retici ifadesinde veya anlamada ├Âne s├╝r├╝len yan─▒t─▒n ele┼čtirisi .

Dilbilgisi halihaz─▒rda liste kavramada herhangi bir ifadeye izin vermektedir.

 expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) |
                     ('=' (yield_expr|testlist_star_expr))*)
...
yield_expr: 'yield' [yield_arg]
yield_arg: 'from' test | testlist
 

Verim bir ifade oldu─čundan, baz─▒lar─▒n─▒n, ├Âzellikle iyi bir kullan─▒m durumu s├Âz etmese de, anlama veya ├╝rete├ž ifadesinde kullanmas─▒ ilgin├ž olmu┼čtur.

CPython ├žekirdek geli┼čtiricileri , ├Âdene─činin kald─▒r─▒lmas─▒n─▒ tart─▒┼č─▒yor . ─░┼čte posta listesinden alakal─▒ bir yaz─▒:

30 Ocak 2017'de saat 19: 05'te Brett Cannon ┼čunu yazd─▒:

Pazar, 29 Ocak 2017, 16:39 Craig Rodrigues yazd─▒:

Her iki yakla┼č─▒mda da iyiyim. ─░┼čleri Python 3'teki gibi b─▒rakmak iyi bir ┼čey de─čil, IMHO.

Benim oyum, s├Âzdiziminden bekledi─činiz ┼čeyi alamad─▒─č─▒n─▒zdan beri bir SyntaxError.

Mevcut davran─▒┼ča dayanan herhangi bir kod, s├╝rd├╝r├╝lemeyecek kadar ak─▒ll─▒ oldu─ču i├žin, bunun bizim i├žin uygun bir yer oldu─čuna kat─▒l─▒yorum.

Oraya ula┼čmak a├ž─▒s─▒ndan, muhtemelen isteyece─čiz:

  • S├ÂzdizimiUyar─▒ veya ─░tiraz
  • 2.7.x'te Py3k uyar─▒s─▒
  • 3.8 y─▒l─▒nda SyntaxError

┼×erefe Nick.

- Nick Coghlan | gco ┼čirketinde ncoghlan | Brisbane, Avustralya

Dahas─▒, bunun hi├ž de iyi bir fikir olmad─▒─č─▒ y├Ân├╝nde i┼čaret eden ola─čan├╝st├╝ bir sorun (10544) var (Python'da yaz─▒lm─▒┼č bir Python uygulamas─▒ olan PyPy, zaten s├Âzdizimi uyar─▒lar─▒ y├╝kseltiyor).

CPython geli┼čtiricileri aksi bize bildirene kadar Alt ├žizgi,: Do koymak yield bir jenerat├Âr ifadesi veya kooperasyon.

return Bir jenerat├Âr├╝ ifadesi

In Python 2 :

Bir jenerat├Âr fonksiyonunda, return ifadenin bir i├žermesine izin verilmez expression_list . Bu ba─člamda, ├ž─▒plak bir return ┼čekilde jenerat├Âr├╝n yap─▒ld─▒─č─▒n─▒ ve StopIteration y├╝kseltilmesine neden olaca─č─▒n─▒ belirtir .

Bir expression_list temelde virg├╝lle ayr─▒lm─▒┼č herhangi bir say─▒da ifadedir - temelde Python 2'de jenerat├Âr├╝ ile durdurabilirsiniz return , ancak bir de─čer d├Ând├╝remezsiniz.

In Python 3 :

Bir jenerat├Âr fonksiyonunda, return ifade, jenerat├Âr├╝n yap─▒ld─▒─č─▒n─▒ ve StopIteration y├╝kseltilmesine neden olaca─č─▒n─▒ belirtir . D├Ând├╝r├╝len de─čer (varsa), in┼ča etmek i├žin bir arg├╝man olarak kullan─▒l─▒r StopIteration ve StopIteration.value nitelik olur .

Dipnotlar

  1. CLU, Sather ve Icon dilleri, ├╝retici konseptini Python'a tan─▒tmak i├žin yap─▒lan teklifte referans al─▒nm─▒┼čt─▒r. Genel fikir, bir i┼člevin i├ž durumunu koruyabilmesi ve kullan─▒c─▒n─▒n talep etmesi ├╝zerine ara veri noktalar─▒ verebilmesidir. Bu , baz─▒ sistemlerde bile bulunmayan Python i┼č par├žac─▒─č─▒ dahil di─čer yakla┼č─▒mlara g├Âre performansta ├╝st├╝n olaca─č─▒na s├Âz verdi .

  2. Bu, ├Ârne─čin, xrange nesnelerin ( range Python 3'te) Iterator yinelenebilir olmalar─▒na ra─čmen, yeniden kullan─▒labilece─činden s olmad─▒─č─▒ anlam─▒na gelir . Listeler gibi, __iter__ y├Ântemleri de yineleyici nesnelerini d├Ând├╝r├╝r.

  3. yield ba┼člang─▒├žta bir ifade olarak tan─▒t─▒lm─▒┼čt─▒, bunun anlam─▒ bir kod blo─čundaki bir sat─▒r─▒n ba┼č─▒nda g├Âr├╝nmesiydi. ┼×imdi yield bir verim ifadesi olu┼čturur. https://docs.python.org/2/reference/simple_stmts.html#grammar-token-yield_stmt Bu de─či┼čiklik, kullan─▒c─▒n─▒n jenerat├Âre veri alabildi─či gibi g├Ânderebilmesi i├žin ├Ânerildi . Veri g├Ândermek i├žin, ki┼činin bir ┼čeye atamas─▒ gerekir ve bunun i├žin bir ifade i┼če yaramaz.


341







yield aynen b├Âyle return - ne diyorsan onu (jenerat├Âr olarak) d├Ând├╝r├╝r. Fark, bir dahaki sefere jenerat├Âr├╝ arad─▒─č─▒n─▒zda, y├╝r├╝tmenin son ├ža─čr─▒dan yield ifadeye kadar ba┼člamas─▒d─▒r . Geri d├Ân├╝┼č├╝n aksine , y─▒─č─▒n ├žer├ževesi bir verim olu┼čtu─čunda temizlenmez, ancak kontrol arayan ki┼čiye geri aktar─▒l─▒r, b├Âylece i┼člev bir daha ├ža─čr─▒ld─▒─č─▒nda durumu devam ettirilir.

Kodunuzda, i┼člev get_child_candidates bir yineleyici gibi davran─▒r, b├Âylece listenizi geni┼čletti─činizde, yeni listeye bir defada bir ├Â─če ekler.

list.extend t├╝kenene kadar bir yineleyici ├ža─č─▒r─▒r. G├Ânderdi─činiz kod ├Ârne─činde, sadece bir tuple d├Ând├╝r├╝p listeye eklemek ├žok daha net olacakt─▒r.


293







S├Âylenecek ilave bir ┼čey daha var: Verimi art─▒ran bir i┼člev yoktur. B├Âyle bir kod yazd─▒m:

 def fib():
    last, cur = 0, 1
    while True: 
        yield cur
        last, cur = cur, last + cur
 

Sonra bunu di─čer kodlarda kullanabilirim:

 for f in fib():
    if some_condition: break
    coolfuncs(f);
 

Baz─▒ sorunlar─▒n basitle┼čtirilmesine ger├žekten yard─▒mc─▒ olur ve baz─▒ ┼čeylerin birlikte ├žal─▒┼čmas─▒n─▒ kolayla┼čt─▒r─▒r.


221







Minimal bir ├žal─▒┼čma ├Ârne─či tercih edenler i├žin, bu etkile┼čimli Python oturumunda meditasyon yap─▒n:

 >>> def f():
...   yield 1
...   yield 2
...   yield 3
... 
>>> g = f()
>>> for i in g:
...   print i
... 
1
2
3
>>> for i in g:
...   print i
... 
>>> # Note that this time nothing was printed
 

201







TL; DR

Bunun yerine:

 def square_list(n):
    the_list = []                         # Replace
    for x in range(n):
        y = x * x
        the_list.append(y)                # these
    return the_list                       # lines
 

Bunu yap:

 def square_yield(n):
    for x in range(n):
        y = x * x
        yield y                           # with this one.
 

Ne zaman kendinizi s─▒f─▒rdan bir liste olu┼čtururken bulursan─▒z, yield her par├ža yerine.

Bu benim ilk "aha" an─▒md─▒.


yield Bir olan ┼čekerli s├Âylemek yolu

bir seri ┼čeyler in┼ča etmek

Ayn─▒ davran─▒┼č:

 >>> for square in square_list(4):
...     print(square)
...
0
1
4
9
>>> for square in square_yield(4):
...     print(square)
...
0
1
4
9
 

Farkl─▒ davran─▒┼č:

Verim tek ge├ži┼čtir : yaln─▒zca bir kez yineleyebilirsiniz. Bir fonksiyonun i├žinde bir verim oldu─čunda ona jenerat├Âr i┼člevi diyoruz . Ve bir yineleyici d├Ând├╝rd├╝─č├╝ ┼čeydir. Bu terimler ortaya ├ž─▒k─▒yor. Bir konteynerin rahatl─▒─č─▒n─▒ kaybediyoruz, ancak gerekti─činde hesaplanan bir dizinin g├╝c├╝n├╝ ve keyfi olarak kazan─▒yoruz.

Verim tembeldir , hesaplamay─▒ durdurur. Verimi olan bir i┼člev asl─▒nda onu ├ža─č─▒rd─▒─č─▒n─▒zda hi├ž ├žal─▒┼čmaz. Kald─▒─č─▒ yeri hat─▒rlayan bir yineleyici nesnesi d├Ând├╝r├╝r . next() Yineleyiciyi her arad─▒─č─▒n─▒zda (bu bir for d├Âng├╝s├╝ i├žinde ger├žekle┼čir) y├╝r├╝tme bir sonraki verime ilerler. return StopIteration'─▒ y├╝kseltir ve seriyi sonland─▒r─▒r (bu for d├Âng├╝s├╝n├╝n do─čal ucu).

Verim ├žok y├Ânl├╝d├╝r . Verilerin hep birlikte depolanmas─▒ gerekmemektedir, her seferinde bir tane kullan─▒labilir hale getirilebilir. Sonsuz olabilir.

 >>> def squares_all_of_them():
...     x = 0
...     while True:
...         yield x * x
...         x += 1
...
>>> squares = squares_all_of_them()
>>> for _ in range(4):
...     print(next(squares))
...
0
1
4
9
 

Birden fazla pasoya ihtiyac─▒n─▒z varsa ve seri ├žok uzun de─čilse, sadece araman─▒z yeterlidir list() :

 >>> list(square_yield(4))
[0, 1, 4, 9]
 

M├╝kemmel bir se├žim, yield ├ž├╝nk├╝ her iki anlam da ge├žerlidir:

verim - ├╝retmek veya sa─člamak (tar─▒mda oldu─ču gibi)

... serideki bir sonraki verileri sa─člar.

verim - yol ver ya da vazge├ž (siyasi iktidarda oldu─ču gibi)

... yineleyici ilerleyene kadar CPU ├žal─▒┼čmas─▒ndan vazge├ž.


186







Kazan├ž size bir jenerat├Âr verir.

 def get_odd_numbers(i):
    return range(1, i, 2)
def yield_odd_numbers(i):
    for x in range(1, i, 2):
       yield x
foo = get_odd_numbers(10)
bar = yield_odd_numbers(10)
foo
[1, 3, 5, 7, 9]
bar
<generator object yield_odd_numbers at 0x1029c6f50>
bar.next()
1
bar.next()
3
bar.next()
5
 

G├Ârd├╝─č├╝n├╝z gibi, ilk durumda foo listenin tamam─▒n─▒ ayn─▒ anda bellekte tutuyor. 5 elementli bir liste i├žin b├╝y├╝k bir sorun de─čil, peki ya 5 milyonluk bir liste istiyorsan? Bu sadece b├╝y├╝k bir haf─▒za yiyici de─čil, ayn─▒ zamanda i┼člevin ├ža─čr─▒ld─▒─č─▒ an─▒ olu┼čturmak i├žin de ├žok zaman al─▒yor.

─░kinci durumda, bar sadece size bir jenerat├Âr verir. Bir jenerat├Âr yinelenebilir - bu, onu bir for d├Âng├╝de vb. Kullanabilece─činiz anlam─▒na gelir , ancak her de─čere yaln─▒zca bir kez eri┼čilebilir. T├╝m de─čerler ayn─▒ zamanda bellekte de saklanmaz; Jenerat├Âr nesnesi, onu en son ne zaman arad─▒─č─▒n─▒zda d├Âng├╝deyken nerede oldu─čunu "hat─▒rlar" - bu yolla, (yani) 50 milyar'a kadar say─▒labilir bir say─▒ kullan─▒yorsan─▒z, 50 milyara kadar sayman─▒z gerekmez. hemen ve saymak i├žin 50 milyar numaray─▒ saklay─▒n.

Yine, bu olduk├ža tart─▒┼čmal─▒ bir ├Ârnek, ger├žekten 50 milyar sayarsan─▒z, itertools kullan─▒rs─▒n─▒z. :)

Jenerat├Ârlerin en basit kullan─▒m ┼čekli budur. S├Âyledi─činiz gibi, bir ├že┼čit y─▒─č─▒n de─či┼čkeni kullanmak yerine arama y─▒─č─▒n─▒nda bir ┼čeyleri yukar─▒ itmek i├žin verimi kullanarak verimli perm├╝tasyonlar yazmak i├žin kullan─▒labilir. Jenerat├Ârler ayr─▒ca ├Âzelle┼čtirilmi┼č a─ča├ž ge├ži┼či ve her t├╝rl├╝ ba┼čka ┼čey i├žin de kullan─▒labilir.


173







Bir jenerat├Âr d├Ând├╝r├╝yor. Python'a ├Âzellikle a┼čina de─čilim, ama C # '─▒n yineleyici bloklar─▒ ile ayn─▒ ┼čey oldu─čuna inan─▒yorum .

Temel fikir, derleyici / terc├╝man / ne olursa olsun, baz─▒ hileler yapan ki┼čidir, b├Âylece arayan ki┼či s├Âz konusu oldu─čunda, bir sonraki aramay─▒ devam ettirebilirler () ve jenerat├Âr y├Ântemi duraklat─▒lm─▒┼č gibi, de─čerleri d├Ând├╝rmeye devam edecektir . ┼×imdi a├ž─▒k bir ┼čekilde, ger├žekten bir y├Ântemi "durduramazs─▒n─▒z", bu nedenle derleyici ┼ču anda nerede oldu─čunuzu ve yerel de─či┼čkenlerin vb. Neye benzedi─čini hat─▒rlaman─▒z i├žin bir durum makinesi olu┼čturur. Bu, bir yineleyici yazmaktan ├žok daha kolayd─▒r.


164







Jenerat├Âr├╝ nas─▒l kullanaca─č─▒m─▒ anlatan pek ├žok cevap aras─▒nda, hen├╝z verilmedi─čini hissetmedi─čim bir cevap var. ─░┼čte programlama dili teorisi cevap:

yield Python deyimi bir jenerat├Âr d├Âner. Python'daki bir ├╝retici, s├╝reklili─či d├Ând├╝ren bir i┼člevdir (ve ├Âzellikle de bir t├╝r korotindir, ancak s├╝reklilikler neler olup bitti─čini anlamak i├žin daha genel bir mekanizmay─▒ temsil eder).

Programlama dilleri teorisindeki s├╝reklilikler ├žok daha temel bir hesaplama t├╝r├╝d├╝r, ancak s─▒kl─▒kla kullan─▒lmazlar, ├ž├╝nk├╝ bunun i├žin mant─▒kl─▒ olmas─▒ ve uygulamas─▒ ├žok zordur. Ancak, devam etmenin ne oldu─ču fikri basit ve a├ž─▒kt─▒r: hen├╝z bitmemi┼č bir hesaplaman─▒n halidir. Bu durumda, de─či┼čkenlerin mevcut de─čerleri, hen├╝z ger├žekle┼čtirilmemi┼č olan i┼člemler ve benzerleri kaydedilir. Ard─▒ndan program─▒n ilerleyen noktalar─▒nda program─▒n de─či┼čkenleri bu duruma s─▒f─▒rlanacak ve kaydedilen i┼člemler ger├žekle┼čtirilebilecek ┼čekilde devam edilebilir.

S├╝reklilikler, bu daha genel bi├žimde, iki ┼čekilde uygulanabilir. Bu call/cc ┼čekilde, program─▒n y─▒─č─▒n─▒ tam anlam─▒yla kaydedilir ve ard─▒ndan devam ba┼člat─▒ld─▒─č─▒nda, y─▒─č─▒n geri y├╝klenir.

Devam eden ge├ži┼č stilinde (CPS), devam etmeler, programc─▒n─▒n a├ž─▒k├ža y├Ânetti─či ve alt rutinlere aktard─▒─č─▒ normal fonksiyonlard─▒r (sadece fonksiyonlar─▒n birinci s─▒n─▒f oldu─ču dillerde). Bu tarzda, program durumu, y─▒─č─▒nda bir yerde bulunan de─či┼čkenlerden ziyade kapaklar (ve bunlarda kodlanm─▒┼č olan de─či┼čkenler) ile temsil edilir. Kontrol ak─▒┼č─▒n─▒ y├Âneten fonksiyonlar devam etmeyi arg├╝man olarak kabul eder (baz─▒ CPS varyasyonlar─▒nda, fonksiyonlar birden fazla devam etmeyi kabul edebilir) ve kontrol ak─▒┼č─▒n─▒ basit├že onlar─▒ ├ža─č─▒rarak ve daha sonra geri d├Ând├╝rerek de─či┼čtirerek i┼čler. Devaml─▒ ge├ži┼č stilinin ├žok basit bir ├Ârne─či ┼č├Âyledir:

 def save_file(filename):
  def write_file_continuation():
    write_stuff_to_file(filename)

  check_if_file_exists_and_user_wants_to_overwrite(write_file_continuation)
 

Bu (├žok basit) ├Ârnekte, programc─▒ dosyay─▒ asl─▒nda bir s├╝reklilik i├žine yazma i┼člemini kaydeder (potansiyel olarak yazmak i├žin pek ├žok ayr─▒nt─▒ i├žeren ├žok karma┼č─▒k bir i┼člem olabilir) ve sonra bu s├╝reklili─či (yani ilk olarak) s─▒n─▒f kapatma) biraz daha i┼člem yapan ba┼čka bir operat├Âre ve sonra gerekirse ├ža─č─▒r─▒r. (Bu tasar─▒m desenini ger├žek GUI programlamas─▒nda ├žok kullan─▒yorum, ├ž├╝nk├╝ bana kod sat─▒rlar─▒n─▒ kaydediyor veya daha da ├Ânemlisi GUI olaylar─▒n─▒n tetiklenmesinden sonra kontrol ak─▒┼č─▒n─▒ y├Ânetmek i├žin.

Bu yaz─▒n─▒n geri kalan─▒, genelli─či kaybetmeden, devam etmeyi CPS olarak kavramsalla┼čt─▒racak, ├ž├╝nk├╝ anla┼č─▒lmas─▒ ve okunmas─▒ ├žok daha kolay.


┼×imdi Python'daki jenerat├Ârler hakk─▒nda konu┼čal─▒m. Jenerat├Ârler, devam etmenin belirli bir alt tipidir. S├╝rd├╝rmeler genel olarak bir hesaplama durumunu (yani program─▒n ├ža─čr─▒ y─▒─č─▒n─▒) kaydedebilse de , jenerat├Ârler yaln─▒zca yineleme durumunu bir yineleyici ├╝zerinden kaydedebilir . Bununla birlikte, bu tan─▒m jenerat├Ârlerin belirli kullan─▒m durumlar─▒ i├žin biraz yan─▒lt─▒c─▒d─▒r. ├ľrne─čin:

 def f():
  while True:
    yield 4
 

Bu a├ž─▒k├ža, davran─▒┼člar─▒ iyi tan─▒mlanm─▒┼č makul bir yinelemektir - jenerat├Âr her seferinde yinelendi─činde, 4 de─čerini d├Ând├╝r├╝r (ve sonsuza dek yapar). Ancak, muhtemelen tekrarlay─▒c─▒lar─▒ (yani for x in collection: do_something(x) ) d├╝┼č├╝n├╝rken akla gelen, prototipik bir tekrarlanabilir tip de─čildir . Bu ├Ârnek, jenerat├Ârlerin g├╝c├╝n├╝ g├Âsterir: e─čer bir ┼čey bir yineleyici ise, bir jenerat├Âr yineleme durumunu koruyabilir.

Yinelemek i├žin: Devam etmeler bir program─▒n y─▒─č─▒n─▒n─▒n durumunu kaydedebilir ve jenerat├Ârler yinelemenin durumunu kaydedebilir. Bu, s├╝reklili─čin jenerat├Ârlerden ├žok daha g├╝├žl├╝ oldu─ču, ancak jenerat├Ârlerin ├žok, ├žok daha kolay oldu─ču anlam─▒na gelir. Dil tasar─▒mc─▒s─▒n─▒n uygulamas─▒ kolayd─▒r ve programc─▒n─▒n kullanmas─▒ daha kolayd─▒r (yazmak i├žin biraz zaman─▒n─▒z varsa, bu sayfay─▒ okumaya devam edin ve ├ža─čr─▒ / cc ile ilgili anlamaya ├žal─▒┼č─▒n ).

Ancak, jenerat├Ârleri basit, ├Âzel bir s├╝rekli ge├ži┼č tarz─▒ olarak kolayca uygulayabilir (ve kavramsalla┼čt─▒rabilirsiniz):

Her yield ├ža─čr─▒ld─▒─č─▒nda, i┼čleve devam─▒ d├Ând├╝rmesini s├Âyler. ─░┼člev tekrar ├ža─čr─▒ld─▒─č─▒nda, b─▒rakt─▒─č─▒ yerden ba┼člar. Dolay─▒s─▒yla, s├Âzde-s├Âzde kodda (yani, s├Âzde kod de─čil, ancak kod de─čil), jenerat├Âr├╝n next y├Ântemi temel olarak ┼č├Âyledir:

 class Generator():
  def __init__(self,iterable,generatorfun):
    self.next_continuation = lambda:generatorfun(iterable)

  def next(self):
    value, next_continuation = self.next_continuation()
    self.next_continuation = next_continuation
    return value
 

nerede yield anahtar kelime asl─▒nda ger├žek jenerat├Âr i┼člevi i├žin s├Âzdizimsel ┼čeker gibi temelde bir ┼čeydir:

 def generatorfun(iterable):
  if len(iterable) == 0:
    raise StopIteration
  else:
    return (iterable[0], lambda:generatorfun(iterable[1:]))
 

Unutmay─▒n ki bu sadece sahte koddur ve jenerat├Ârlerin Python'daki ger├žek uygulamas─▒ daha karma┼č─▒kt─▒r. Ancak, neler olup bitti─čini anlama al─▒┼čt─▒rmas─▒ olarak, jenerat├Âr nesnelerini yield anahtar kelimeyi kullanmadan uygulamak i├žin s├╝rekli ge├ži┼č stilini kullanmaya ├žal─▒┼č─▒n .


152







─░┼čte d├╝z dilde bir ├Ârnek. Y├╝ksek seviye insan kavramlar─▒ ile d├╝┼č├╝k seviye Python kavramlar─▒ aras─▒nda bir yaz─▒┼čma sa─člayaca─č─▒m.

Bir dizi dizide i┼člem yapmak istiyorum, ancak bu dizinin yarat─▒lmas─▒yla kendimi rahats─▒z etmek istemiyorum, sadece yapmak istedi─čim i┼čleme odaklanmak istiyorum. Bu y├╝zden, a┼ča─č─▒dakileri yap─▒yorum:

  • Sizi arar─▒m ve size belirli bir ┼čekilde ├╝retilen bir say─▒ dizisi istedi─čimi s├Âylerim ve algoritman─▒n ne oldu─čunu size bildiririm.
    Bu ad─▒m def , jenerat├Âr fonksiyonunun ba┼člat─▒lmas─▒na kar┼č─▒l─▒k gelir , yani a i├žeren fonksiyon yield .
  • Bir s├╝re sonra size, "Tamam, bana say─▒lar─▒n s─▒ras─▒n─▒ anlatmaya haz─▒rlan─▒n" dedim.
    Bu ad─▒m, bir jenerat├Âr nesnesini d├Ând├╝ren jenerat├Âr i┼člevinin ├ža─čr─▒lmas─▒na kar┼č─▒l─▒k gelir. Bana hen├╝z herhangi bir numara s├Âylemedi─činizi unutmay─▒n; Sadece ka─č─▒t ve kalemini al.
  • "Bana bir sonraki numaray─▒ s├Âyle" derim ve sen bana ilk numaray─▒ s├Âylersin; ondan sonra, bir sonraki numaray─▒ sormam─▒ beklersin. Nerede oldu─čunuzu, daha ├Ânce hangi say─▒lar─▒ s├Âyledi─činizi ve bir sonraki say─▒n─▒n ne oldu─čunu hat─▒rlamak sizin i┼činiz. Detaylar umurumda de─čil.
    Bu ad─▒m .next() , jenerat├Âr nesnesinin ├ža─čr─▒lmas─▒na kar┼č─▒l─▒k gelir .
  • ÔÇťbir ├Ânceki ad─▒m─▒ tekrarlay─▒n,ÔÇŁ
  • sonunda bir sona gelebilir. Bana bir numara s├Âylemiyorsun; sadece ba─č─▒rd─▒n, "atlar─▒n─▒ tut! ─░┼čim bitti! Art─▒k numara yok!"
    Bu ad─▒m, i┼čini sona erdiren ve bir StopIteration istisna olu┼čturmak i├žin jenerat├Âr nesnesine tekab├╝l eder Jenerat├Âr fonksiyonunun istisnay─▒ artt─▒rmas─▒ gerekmez. ─░┼člev bitti─činde veya ├ž─▒kt─▒─č─▒nda otomatik olarak kald─▒r─▒l─▒r a return .

Bir jenerat├Âr├╝n yapt─▒─č─▒ budur (a i├žeren bir fonksiyon yield ); y├╝r├╝tmeye ba┼člar, ne zaman yaparsa duraklar yield ve bir .next() de─čer istendi─činde en son oldu─ču noktadan devam eder. S─▒ral─▒ olarak nas─▒l de─čer talep edilece─čini a├ž─▒klayan Python'un yineleyici protokol├╝ ile tasar─▒ma m├╝kemmel uyum sa─člar.

Yineleyici protokol├╝n├╝n en ├╝nl├╝ kullan─▒c─▒s─▒ for Python'daki komuttur. Ne zaman bir yaparsan:

 for item in sequence:
 

yukar─▒da a├ž─▒kland─▒─č─▒ gibi sequence bir liste, bir dize, bir s├Âzl├╝k veya bir jenerat├Âr nesnesinin ├Ânemi yoktur ; sonu├ž ayn─▒d─▒r: bir dizideki ├Â─čeleri tek tek okuyorsunuz.

Not def Bir i├žeren bir i┼člev i├žerebilen ve yield anahtar kelime bir jenerat├Âr olu┼čturmak i├žin tek yol de─čildir; bu, yaratman─▒n en kolay yolu.

Daha do─čru bilgi i├žin, Python belgelerinde yineleyici t├╝rleri , verim ifadesi ve jenerat├Ârler hakk─▒nda bilgi edinin .


134


2008-10-24





Bir├žok cevap neden yield bir jenerat├Âr olu┼čturmak i├žin kulland─▒─č─▒n─▒z─▒ g├Âsterirken, bunun i├žin daha fazla kullan─▒m alan─▒ vard─▒r yield . Bilginin iki kod blo─ču aras─▒nda aktar─▒lmas─▒n─▒ sa─člayan bir coroutine yapmak olduk├ža kolayd─▒r. yield Bir jenerat├Âr olu┼čturmak i├žin kullanma konusunda verilmi┼č olan iyi ├Ârneklerin hi├žbirini tekrar etmeyece─čim .

yield A┼ča─č─▒daki kodda bir i┼člemin ne yapt─▒─č─▒n─▒ anlaman─▒za yard─▒mc─▒ olmak i├žin, parma─č─▒n─▒z─▒ kullanarak bir kodu i├žeren ├ževrimi takip edebilirsiniz yield . Parma─č─▒n─▒z─▒ her vurdu─čunda, yield girmek i├žin a next veya a beklemeniz send gerekir. A next arand─▒─č─▒nda, yield kodun ├╝zerinden ÔÇťsa─č─▒ndaki kod yield de─čerlendirilir ve arayana d├ÂnerÔÇŁ tu┼čuna basana kadar izler ve sonra beklersiniz. Ne zaman next tekrar denir, kod arac─▒l─▒─č─▒yla ba┼čka d├Âng├╝ ger├žekle┼čtirin. Ancak, bir e┼čyordam─▒n i├žinde, dikkat edece─čiz yield ayr─▒ca kullan─▒labilir send arayan bir de─čer g├Ânderecek | ├ó ÔéČ i├žine veren fonksiyonu. A send verilirse, o zaman yield g├Ânderilen de─čeri al─▒r ve sol tarafa do─čru da─č─▒t─▒r - daha sonra yield tekrar basana kadar kodun ilerlemesi devam eder (sondaki de─čeri (sanki next aranan gibi)).

├ľrne─čin:

 >>> def coroutine():
...     i = -1
...     while True:
...         i += 1
...         val = (yield i)
...         print("Received %s" % val)
...
>>> sequence = coroutine()
>>> sequence.next()
0
>>> sequence.next()
Received None
1
>>> sequence.send('hello')
Received hello
2
>>> sequence.close()
 

119







Ba┼čka bir yield kullan─▒m ve anlam var (Python 3.3'ten beri):

 yield from <expr>
 

G├Ânderen PEP 380 - dizimi i├žin yetki verme bir Subgenerator i├žin :

Bir jenerat├Âr├╝n faaliyetlerinin bir b├Âl├╝m├╝n├╝ ba┼čka bir jenerat├Âre devretmesi i├žin bir s├Âzdizimi ├Ânerilmi┼čtir. Bu, 'verim' i├žeren bir kod b├Âl├╝m├╝n├╝n d─▒┼čar─▒ ├ž─▒kar─▒l─▒p ba┼čka bir jenerat├Âre yerle┼čtirilmesine izin verir. Ek olarak, alt ├╝retecin bir de─čerle d├Ânmesine izin verilir ve de─čer, yetki verilmi┼č ├╝rete├ž i├žin kullan─▒labilir duruma getirilir.

Yeni s├Âzdizimi, bir jenerat├Âr ba┼čka bir ki┼či taraf─▒ndan ├╝retilen de─čerleri yeniden ├╝retti─činde optimizasyon i├žin baz─▒ f─▒rsatlar da a├žar.

Dahas─▒, bu (Python 3.5'ten beri) tan─▒tacakt─▒r:

 async def new_coroutine(data):
   ...
   await blocking_action()
 

Korotinler normal bir jenerat├Âr ile kar─▒┼čt─▒r─▒lmamas─▒ i├žin (bug├╝n yield her ikisinde de kullan─▒lmaktad─▒r).


112







T├╝m harika cevaplar, ancak yeni ba┼člayanlar i├žin biraz zor.

San─▒r─▒m return ifadeyi ├Â─črendin .

Bir analoji olarak return ve yield ikizler. return 'geri ver ve dur' anlam─▒na gelirken, 'verim' 'geri gel, ancak devam' anlam─▒na

  1. ─░le num_list almaya ├žal─▒┼č─▒n return .
 def num_list(n):
    for i in range(n):
        return i
 

├çal─▒┼čt─▒r:

 In [5]: num_list(3)
Out[5]: 0
 

G├Âr├╝yorsun, listeden ziyade sadece bir numara al─▒yorsun. return Asla mutlu olmana izin vermez, sadece bir kere uygular ve i┼čten ├ž─▒kar.

  1. Orada geliyor yield

De─či┼čtir return ile yield :

 In [10]: def num_list(n):
    ...:     for i in range(n):
    ...:         yield i
    ...:

In [11]: num_list(3)
Out[11]: <generator object num_list at 0x10327c990>

In [12]: list(num_list(3))
Out[12]: [0, 1, 2]
 

┼×imdi, t├╝m say─▒lar─▒ elde etmek i├žin sen kazand─▒n.

Kar┼č─▒la┼čt─▒rarak return hangi bir kez ve durur ├žal─▒┼č─▒r yield sen rendelenmi┼č kez ├žal─▒┼č─▒r. Sen yorumlayabilir return olarak return one of them ve yield s─▒ra return all of them . Buna denir iterable .

  1. Bir ad─▒m daha biz yeniden yazabilirsiniz yield beyan─▒na return
 In [15]: def num_list(n):
    ...:     result = []
    ...:     for i in range(n):
    ...:         result.append(i)
    ...:     return result

In [16]: num_list(3)
Out[16]: [0, 1, 2]
 

Bunun hakk─▒nda ├žekirdek yield .

Bir liste return ├ž─▒kt─▒s─▒ ile nesne yield ├ž─▒kt─▒s─▒ aras─▒ndaki fark ┼čudur:

Bir liste nesnesinden her zaman [0, 1, 2] al─▒rs─▒n─▒z, ancak onlar─▒ yaln─▒zca bir yield kez ' nesne ├ž─▒kt─▒s─▒ndan' alabilirdi. B├Âylece, generator g├Âr├╝nt├╝lendi─či gibi yeni bir ad nesnesine sahiptir Out[11]: <generator object num_list at 0x10327c990> .

Sonu├ž olarak, onu par├žalamak i├žin bir metafor olarak:

  • return ve yield ikizler
  • list ve generator ikizler

98







Python, sanki Python onlar i├žin s├Âzdizimsel ┼čeker sa─člam─▒yormu┼č gibi, asl─▒nda jenerat├Ârlerin nas─▒l uygulanaca─č─▒na dair baz─▒ Python ├Ârnekleri:

Bir Python ├╝reticisi olarak:

 from itertools import islice

def fib_gen():
    a, b = 1, 1
    while True:
        yield a
        a, b = b, a + b

assert [1, 1, 2, 3, 5] == list(islice(fib_gen(), 5))
 

Jenerat├Ârler yerine s├Âzc├╝ksel kapan─▒┼člar─▒n kullan─▒lmas─▒

 def ftake(fnext, last):
    return [fnext() for _ in xrange(last)]

def fib_gen2():
    #funky scope due to python2.x workaround
    #for python 3.x use nonlocal
    def _():
        _.a, _.b = _.b, _.a + _.b
        return _.a
    _.a, _.b = 0, 1
    return _

assert [1,1,2,3,5] == ftake(fib_gen2(), 5)
 

Jenerat├Ârler yerine nesne kapan─▒┼člar─▒n─▒ kullanmak ( ClosuresAndObjectsAreEquivalent )

 class fib_gen3:
    def __init__(self):
        self.a, self.b = 1, 1

    def __call__(self):
        r = self.a
        self.a, self.b = self.b, self.a + self.b
        return r

assert [1,1,2,3,5] == ftake(fib_gen3(), 5)
 

93







"Jenerat├Ârlerin h─▒zl─▒ bir a├ž─▒klamas─▒ i├žin Beazley'in" Python: Essential Reference "sayfas─▒n─▒ 19. sayfas─▒n─▒ okuyaca─č─▒m" yazacakt─▒m, fakat pek ├žok ki┼či zaten iyi a├ž─▒klamalar yapt─▒.

Ayr─▒ca, yield coroutinlerde, jenerat├Âr i┼člevlerinde kullan─▒mlar─▒n─▒n ikilisi olarak kullan─▒labilece─čine dikkat edin . Kod pasaj─▒n─▒zla ayn─▒ kullan─▒m olmasa da, (yield) bir i┼člevde ifade olarak kullan─▒labilir. Bir arayan, y├Ântemi kullanarak metoda bir de─čer g├Ânderdi─činde send() , coroutine bir sonraki (yield) ifadeye rastlanana kadar y├╝r├╝t├╝l├╝r .

Jenerat├Ârler ve koroinler veri ak─▒┼č─▒ tipi uygulamalar─▒ ayarlamak i├žin harika bir yoldur. ─░fadenin yield i┼člevlerde di─čer kullan─▒mlar─▒ hakk─▒nda bilgi sahibi olman─▒n faydal─▒ olaca─č─▒n─▒ d├╝┼č├╝nd├╝m .


87







Bir programlama a├ž─▒s─▒ndan bak─▒ld─▒─č─▒nda, yineleyiciler olarak uygulan─▒r thunks .

E┼čzamanl─▒ ├žal─▒┼čt─▒rma i├žin yineleyiciler, jenerat├Ârler ve i┼č par├žac─▒─č─▒ havuzlar─▒, e┼čyalar olarak (ayn─▒ zamanda ads─▒z i┼člevler de denir) uygulamak i├žin, biri bir da─č─▒t─▒c─▒ya sahip olan bir kapanma nesnesine g├Ânderilen mesajlar─▒ kullan─▒r ve da─č─▒t─▒c─▒ "iletilere" yan─▒t verir.

http://en.wikipedia.org/wiki/Message_passing

" next " " iter " ├ža─čr─▒s─▒ taraf─▒ndan olu┼čturulan bir kapanmaya g├Ânderilen bir mesajd─▒r .

Bu hesaplamay─▒ uygulaman─▒n bir├žok yolu vard─▒r. Mutasyon kulland─▒m, ancak mevcut de─čeri ve bir sonraki vericiyi d├Ând├╝rerek mutasyon olmadan yapmak kolayd─▒r.

─░┼čte R6RS yap─▒s─▒n─▒ kullanan bir g├Âsteri, ancak anlambilim kesinlikle Python's ile ayn─▒d─▒r. Ayn─▒ hesaplama modeli ve Python'da yeniden yazmak i├žin yaln─▒zca s├Âzdizimindeki bir de─či┼čiklik gerekiyor.

 Welcome to Racket v6.5.0.3.

-> (define gen
     (lambda (l)
       (define yield
         (lambda ()
           (if (null? l)
               'END
               (let ((v (car l)))
                 (set! l (cdr l))
                 v))))
       (lambda(m)
         (case m
           ('yield (yield))
           ('init  (lambda (data)
                     (set! l data)
                     'OK))))))
-> (define stream (gen '(1 2 3)))
-> (stream 'yield)
1
-> (stream 'yield)
2
-> (stream 'yield)
3
-> (stream 'yield)
'END
-> ((stream 'init) '(a b))
'OK
-> (stream 'yield)
'a
-> (stream 'yield)
'b
-> (stream 'yield)
'END
-> (stream 'yield)
'END
->
 

87







─░┼čte basit bir ├Ârnek:

 def isPrimeNumber(n):
    print "isPrimeNumber({}) call".format(n)
    if n==1:
        return False
    for x in range(2,n):
        if n % x == 0:
            return False
    return True

def primes (n=1):
    while(True):
        print "loop step ---------------- {}".format(n)
        if isPrimeNumber(n): yield n
        n += 1

for n in primes():
    if n> 10:break
    print "wiriting result {}".format(n)
 

Çıktı:

 loop step ---------------- 1
isPrimeNumber(1) call
loop step ---------------- 2
isPrimeNumber(2) call
loop step ---------------- 3
isPrimeNumber(3) call
wiriting result 3
loop step ---------------- 4
isPrimeNumber(4) call
loop step ---------------- 5
isPrimeNumber(5) call
wiriting result 5
loop step ---------------- 6
isPrimeNumber(6) call
loop step ---------------- 7
isPrimeNumber(7) call
wiriting result 7
loop step ---------------- 8
isPrimeNumber(8) call
loop step ---------------- 9
isPrimeNumber(9) call
loop step ---------------- 10
isPrimeNumber(10) call
loop step ---------------- 11
isPrimeNumber(11) call
 

Bir Python geli┼čtiricisi de─čilim, ancak bana yield program ak─▒┼č─▒n─▒n konumunu g├Âsteriyor ve bir sonraki d├Âng├╝ "verim" konumundan ba┼čl─▒yor. Bu pozisyonda bekliyor gibi g├Âr├╝n├╝yor ve bundan hemen ├Ânce d─▒┼čar─▒ya bir de─čer d├Ând├╝rmek ve bir dahaki sefere ├žal─▒┼čmaya devam ediyor.

─░lgin├ž ve g├╝zel bir yetenek gibi g├Âr├╝n├╝yor: D


77







─░┼čte ne yapt─▒─č─▒n─▒n zihinsel bir g├Âr├╝nt├╝s├╝ yield .

Bir i┼č par├žac─▒─č─▒n─▒n bir y─▒─č─▒na sahip oldu─čunu d├╝┼č├╝nmeyi seviyorum (bu ┼čekilde uygulanmad─▒─č─▒nda bile).

Normal bir i┼člev ├ža─čr─▒ld─▒─č─▒nda, yerel de─či┼čkenlerini y─▒─č─▒na koyar, bir miktar hesaplama yapar, ard─▒ndan y─▒─č─▒n─▒ temizler ve geri d├Ând├╝r├╝r. Yerel de─či┼čkenlerinin de─čerleri bir daha asla g├Âr├╝lmez.

Bir yield i┼člevde, kodu ├žal─▒┼čmaya ba┼člad─▒─č─▒nda (yani i┼člev next() ├ža─čr─▒ld─▒ktan sonra , y├Ântemi ├ža─čr─▒lan bir jenerat├Âr nesnesinin d├Ând├╝r├╝lmesi), benzer ┼čekilde yerel de─či┼čkenleri y─▒─č─▒na koyar ve bir s├╝re hesaplar. Ama sonra, yield ifadeye ├žarpt─▒─č─▒nda, y─▒─č─▒n─▒n bir b├Âl├╝m├╝n├╝ temizlemeden ve geri d├Ând├╝rmeden ├Ânce, yerel de─či┼čkenlerinin bir anl─▒k g├Âr├╝nt├╝s├╝n├╝ al─▒r ve bunlar─▒ jenerat├Âr nesnesine depolar. Ayr─▒ca halihaz─▒rda kodunda bulundu─ču yeri de yazar (├Ârne─čin, belirli bir yield ifade).

Yani jenerat├Âr├╝n ├╝zerinde durdu─ču donmu┼č bir fonksiyon.

Daha next() sonra ├ža─čr─▒ld─▒─č─▒nda, fonksiyonun e┼čyalar─▒n─▒ y─▒─č─▒na al─▒r ve yeniden canland─▒r─▒r. Bu fonksiyon, kald─▒─č─▒ yerden hesaplamaya devam ediyor, so─čuk hava deposunda sonsuzluk harcad─▒─č─▒ ger├že─čini habersiz.

A┼ča─č─▒daki ├Ârnekleri kar┼č─▒la┼čt─▒r─▒n:

 def normalFunction():
    return
    if False:
        pass

def yielderFunction():
    return
    if False:
        yield 12
 

─░kinci i┼člevi ├ža─č─▒rd─▒─č─▒m─▒zda, birincisine ├žok farkl─▒ davran─▒r. yield ─░fadesi ula┼č─▒lamaz olabilir, ama mevcut yerde ise, biz u─čra┼č─▒yoruz do─čas─▒n─▒ de─či┼čtirir.

 >>> yielderFunction()
<generator object yielderFunction at 0x07742D28>
 

├ça─čr─▒lar yielderFunction() kodunu ├žal─▒┼čt─▒rmaz, fakat kodun d─▒┼č─▒nda bir jenerat├Âr yapar. (Belki de bu t├╝r ┼čeyleri yielder okunabilirlik ├Âneki ile adland─▒rmak iyi bir fikirdir .)

 >>> gen = yielderFunction()
>>> dir(gen)
['__class__',
 ...
 '__iter__',    #Returns gen itself, to make it work uniformly with containers
 ...            #when given to a for loop. (Containers return an iterator instead.)
 'close',
 'gi_code',
 'gi_frame',
 'gi_running',
 'next',        #The method that runs the function's body.
 'send',
 'throw']
 

gi_code Ve gi_frame dondurulmu┼č devlet sakland─▒─č─▒ yere alanlard─▒r. Onlar─▒ ara┼čt─▒r─▒rken dir(..) , yukar─▒daki zihinsel modelimizin g├╝venilir oldu─čunu onaylayabiliriz.


61







Her cevab─▒n ├Ânerdi─či gibi, yield bir dizi ├╝reteci olu┼čturmak i├žin kullan─▒l─▒r. Dinamik olarak bir dizi olu┼čturmak i├žin kullan─▒l─▒r. ├ľrne─čin, bir dosyay─▒ bir a─č ├╝zerinde sat─▒r sat─▒r okurken, yield i┼člevi a┼ča─č─▒daki gibi kullanabilirsiniz :

 def getNextLines():
   while con.isOpen():
       yield con.read()
 

Kodunuzda a┼ča─č─▒daki gibi kullanabilirsiniz:

 for line in getNextLines():
    doSomeThing(line)
 

Y├╝r├╝tme Kontrol Transferi gotcha

Uygulama kontrol├╝, for verim ├žal─▒┼čt─▒r─▒ld─▒─č─▒nda getNextLines () 'den d├Âng├╝ye aktar─▒l─▒r . B├Âylece, getNextLines () her ├ža─čr─▒ld─▒─č─▒nda, y├╝r├╝tme en son duraklat─▒ld─▒─č─▒ yerden ba┼člar.

B├Âylece k─▒sacas─▒, a┼ča─č─▒daki kodla bir i┼člev

 def simpleYield():
    yield "first time"
    yield "second time"
    yield "third time"
    yield "Now some useful value {}".format(12)

for i in simpleYield():
    print i
 

basacak

 "first time"
"second time"
"third time"
"Now some useful value 12"
 

52







Verim bir nesnedir

Bir return fonksiyondaki A tek bir de─čer d├Ând├╝r├╝r.

Bir fonksiyonun ├žok b├╝y├╝k bir de─čer k├╝mesi d├Ând├╝rmesini istiyorsan─▒z , kullan─▒n yield .

Daha da ├Ânemlisi, yield bir engeldir .

CUDA dilinde bariyer gibi, tamamlan─▒ncaya kadar kontrol├╝ transfer etmeyecektir.

Yani, fonksiyonunuzdaki kodu en ba┼čtan isabet edene kadar ├žal─▒┼čt─▒racakt─▒r yield . Ard─▒ndan, d├Âng├╝n├╝n ilk de─čerini d├Ând├╝r├╝r.

Ard─▒ndan, di─čer t├╝m ├ža─čr─▒lar, fonksiyonda yazd─▒─č─▒n─▒z d├Âng├╝y├╝ bir kez daha ├žal─▒┼čt─▒r─▒r ve d├Ând├╝r├╝len herhangi bir de─čer bulunana kadar bir sonraki de─čeri d├Ând├╝r├╝r.


46







├ľzet olarak, yield ifade, i┼člevinizi generator orijinal i┼člevinizin g├Âvdesinin etraf─▒na sararak ad─▒ verilen ├Âzel bir nesne ├╝reten bir fabrikaya d├Ân├╝┼čt├╝r├╝r . Zaman generator tekrarlan─▒r sonraki ula┼čana kadar, bu i┼člevini y├╝r├╝t├╝r yield sonra iletilen de─čerin y├╝r├╝t├╝lmesine ve de─čerlendirir ask─▒ya yield . Y├╝r├╝tme yolu i┼člevden ├ž─▒kana kadar bu i┼člemi her yinelemede tekrar eder. ├ľrne─čin,

 def simple_generator():
    yield 'one'
    yield 'two'
    yield 'three'

for i in simple_generator():
    print i
 

basit├že ├ž─▒kt─▒lar

 one
two
three
 

G├╝├ž, bir sekans─▒ hesaplayan bir d├Âng├╝ ile jenerat├Âr├╝ kullanmaktan gelir, jenerat├Âr, hesaplaman─▒n bir sonraki sonucunu 'vermek' i├žin her seferinde durma d├Âng├╝s├╝n├╝ ├žal─▒┼čt─▒r─▒r, bu ┼čekilde an─▒nda bir liste hesaplar, faydas─▒ haf─▒zad─▒r. ├Âzellikle b├╝y├╝k hesaplamalar i├žin kaydedildi

range Yinelenebilir say─▒ aral─▒─č─▒ ├╝reten kendi i┼člevlerinizi olu┼čturmak istedi─činizi varsayal─▒m.

 def myRangeNaive(i):
    n = 0
    range = []
    while n < i:
        range.append(n)
        n = n + 1
    return range
 

ve bu ┼čekilde kullan─▒n;

 for i in myRangeNaive(10):
    print i
 

Ama bu verimsiz ├ž├╝nk├╝

  • Yaln─▒zca bir kez kulland─▒─č─▒n─▒z bir dizi olu┼čturursunuz (bu, belle─či bo┼ča harcar)
  • Bu kod asl─▒nda o dizinin ├╝zerine iki kez d├Ân├╝yor! :(

Neyse ki Guido ve ekibi jenerat├Ârler geli┼čtirebilecek kadar c├Âmertlerdi;

 def myRangeSmart(i):
    n = 0
    while n < i:
       yield n
       n = n + 1
    return

for i in myRangeSmart(10):
    print i
 

┼×imdi, her yinelemede, ├ža─čr─▒lan jenerat├Âr ├╝zerindeki bir i┼člev next() , i┼člevi durdu─ču ve de─čeri 'veren' bir 'verim' ifadesine ula┼čana veya i┼člevin sonuna ula┼čana kadar i┼člevi ger├žekle┼čtirir. Bu durumda, ilk ├ža─čr─▒da, next() "c" 'ye g├Âre "c├╝mle" ye ve "n" verimine kadar uygular, bir sonraki aramada "art─▒┼č" deyimini y├╝r├╝t├╝r, "s├╝re" ye geri d├Âner, de─čerlendirir ve do─čruysa durur 'n' verimi, s├╝re ko┼čulu yanl─▒┼č d├Ânene ve jenerat├Âr fonksiyonun sonuna atlayana kadar bu ┼čekilde devam edecektir.


46







(A┼ča─č─▒daki cevab─▒m sadece Python jenerat├Âr├╝n├╝ kullanma perspektifinden bahseder , baz─▒ y─▒─č─▒n ve y─▒─č─▒n manip├╝lasyon hilelerini i├žeren , jenerat├Âr mekanizmas─▒n─▒n alt─▒nda yatan uygulamay─▒ de─čil .)

Bir python i┼člevinde yield yerine kullan─▒ld─▒─č─▒nda return , bu i┼člev ├Âzel olarak adland─▒r─▒lan ├Âzel bir ┼čeye d├Ân├╝┼čt├╝r├╝l├╝r generator function . Bu i┼člev generator t├╝r├╝nde bir nesne d├Ând├╝r├╝r . Anahtar kelime ├Âzel olarak bu t├╝r fonksiyon tedavisi i├žin piton derleyici bildirmek i├žin bir bayrakt─▒r. Normal fonksiyonlar, ondan bir de─čer d├Ând├╝r├╝ld├╝─č├╝nde sona erecektir. Ancak, derleyicinin yard─▒m─▒yla, jenerat├Âr i┼člevi yeniden ba┼člat─▒labilir olarak d├╝┼č├╝n├╝lebilir . Yani, y├╝r├╝tme i├žeri─či geri y├╝klenecek ve y├╝r├╝tme son ├žal─▒┼čt─▒rmadan itibaren devam edecek. A├ž─▒k├ža geri d├Ân├╝┼č├╝ ├ža─č─▒r─▒ncaya kadar (ki bu yinelemeli protokol├╝n bir par├žas─▒ olan) bir istisna olu┼čturacak veya fonksiyonun sonuna ula┼čacak. Ben yakla┼č─▒k referanslar bir s├╝r├╝ buldum ama bu bir gelen en digestable oldu─čunu. yield StopIteration generator https://docs.python.org/dev/howto/functional.html%23generators#generators functional programming perspective

(┼×imdi, arkas─▒ndaki mant─▒k generator ve iterator kendi anlay─▒┼č─▒ma dayanarak bahsetmek istiyorum . Umar─▒m bu, yineleyici ve jenerat├Âr├╝n temel motivasyonunu kavraman─▒za yard─▒mc─▒ olabilir . Bu kavram, C # gibi di─čer dillerde de ortaya ├ž─▒kar.)

Anlad─▒─č─▒m kadar─▒yla, bir grup veriyi i┼člemek istedi─čimizde, genellikle verileri bir yere depolar ve sonra birer birer i┼čleriz. Ancak bu saf yakla┼č─▒m sorunludur. Veri hacmi ├žok b├╝y├╝kse, bunlar─▒ ├Ânceden bir b├╝t├╝n olarak saklamak pahal─▒d─▒r. ├ľyleyse data do─črudan kendisini saklamak yerine , neden metadata dolayl─▒ olarak bir t├╝r depolam─▒yorsunuz the logic how the data is computed ?

Bu meta verileri sarmak i├žin 2 yakla┼č─▒m vard─▒r.

  1. OO yakla┼č─▒m─▒, meta verileri sarar─▒z as a class . Bu, iterator yineleyici protokol├╝n├╝ uygulayanlar (yani y├Ântem __next__() ve __iter__() y├Ântemler). Bu ayn─▒ zamanda yayg─▒n olarak g├Âr├╝len yineleyici tasar─▒m desenidir .
  2. ─░┼člevsel yakla┼č─▒m, meta verileri sarar─▒z as a function . Bu s├Âzde generator function . Ancak kaputun alt─▒nda, d├Ând├╝r├╝len generator object hala IS-A yineleyici, ├ž├╝nk├╝ yineleyici protokol├╝n├╝ de uygular.

Her iki durumda da, bir yineleyici olu┼čturulur, yani istedi─činiz verileri size verebilecek bir nesne. OO yakla┼č─▒m─▒ biraz karma┼č─▒k olabilir. Neyse, hangisini kullanman sana kalm─▒┼č.


46







Pek ├žok insan kullanmak return yerine kullan─▒r yield , ancak baz─▒ durumlarda yield ├žal─▒┼čmak daha verimli ve daha kolay olabilir.

─░┼čte yield kesinlikle en iyisi olan bir ├Ârnek :

d├Ân├╝┼č (i┼člevinde)

 import random

def return_dates():
    dates = [] # With 'return' you need to create a list then return it
    for i in range(5):
        date = random.choice(["1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th"])
        dates.append(date)
    return dates
 

verim (i┼člevinde)

 def yield_dates():
    for i in range(5):
        date = random.choice(["1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th"])
        yield date # 'yield' makes a generator automatically which works
                   # in a similar way. This is much more efficient.
 

├ça─čr─▒ fonksiyonlar─▒

 dates_list = return_dates()
print(dates_list)
for i in dates_list:
    print(i)

dates_generator = yield_dates()
print(dates_generator)
for i in dates_generator:
    print(i)
 

Her iki i┼člev de ayn─▒ ┼čeyi yapar, ancak yield be┼č yerine ├╝├ž sat─▒r kullan─▒r ve endi┼čelenecek bir daha az de─či┼čkene sahiptir.

Bu kodun sonucudur:


Çıktı

G├Ârd├╝─č├╝n├╝z gibi her iki fonksiyon da ayn─▒ ┼čeyi yap─▒yor. Tek fark return_dates() bir liste yield_dates() verir ve bir jenerat├Âr verir.

Ger├žek hayattan bir ├Ârnek, bir dosyay─▒ sat─▒r sat─▒r okumak veya yaln─▒zca bir jenerat├Âr yapmak gibi bir ┼čey olabilir.


45







Ne oldu─čunu anlamak i├žin kolay bir ├Ârnek: yield

 def f123():
    for _ in range(4):
        yield 1
        yield 2


for i in f123():
    print i
 

Çıktı:

 1 2 1 2 1 2 1 2
 

42







yield bir fonksiyon i├žin d├Ân├╝┼č eleman─▒ gibidir. Fark, yield eleman─▒n bir jenerat├Âre d├Ân├╝┼čmesidir. Bir jenerat├Âr 'bir ┼čey elde edilinceye kadar' bir fonksiyon gibi davran─▒r. Jenerat├Âr bir daha aranana kadar durur ve tam olarak ayn─▒ noktadan devam eder. 'Verilmi┼č olan' de─čerlerin t├╝m├╝n├╝ bir s─▒rada arayarak alabilirsiniz list(generator()) .


38







yield Anahtar kelime basit├že sonu├žlar─▒n─▒ d├Ând├╝rmek toplar. yield Gibi d├╝┼č├╝n├╝n return +=


36







─░┼čte yield fibonacci serisini hesaplamak i├žin basit bir yakla┼č─▒m:

 def fib(limit=50):
    a, b = 0, 1
    for i in range(limit):
       yield b
       a, b = b, a+b
 

Bunu REPL'inize girip ard─▒ndan aramay─▒ denedi─činizde, gizemli bir sonu├ž elde edersiniz:

 >>> fib()
<generator object fib at 0x7fa38394e3b8>
 

Bunun nedeni, yield bir jenerat├Âr olu┼čturmak istedi─činiz Python'a sinyal verilmesidir , yani talep ├╝zerine de─čer ├╝reten bir nesnedir.

Peki, bu de─čerleri nas─▒l ├╝retiyorsunuz? Bu ya do─črudan yerle┼čik i┼člev kullan─▒larak next ya da dolayl─▒ olarak de─čer t├╝keten bir yap─▒ya beslenerek yap─▒labilir.

Yerle┼čik next() i┼člevi kullanarak, jenerat├Âr├╝ do─črudan bir de─čer ├╝retmeye zorlayarak .next / __next__ ├ža─č─▒r─▒rs─▒n─▒z:

 >>> g = fib()
>>> next(g)
1
>>> next(g)
1
>>> next(g)
2
>>> next(g)
3
>>> next(g)
5
 

Dolayl─▒ olarak, fib bir for d├Âng├╝ye, list ba┼člat─▒c─▒ya, tuple ba┼člat─▒c─▒ya veya de─čer ├╝reten / ├╝reten bir nesne bekleyen ba┼čka bir ┼čey sa─člarsan─▒z , jenerat├Âr taraf─▒ndan, ba┼čka bir de─čer ├╝retilinceye kadar "t├╝ketilir" olur (ve geri d├Âner) :

 results = []
for i in fib(30):       # consumes fib
    results.append(i) 
# can also be accomplished with
results = list(fib(30)) # consumes fib
 

Benzer ┼čekilde, tuple ba┼člat─▒c─▒ ile:

 >>> tuple(fib(5))       # consumes fib
(1, 1, 2, 3, 5)
 

Bir jenerat├Âr, tembel oldu─ču anlam─▒ndaki bir fonksiyondan farkl─▒d─▒r. Bunu, yerel durumunu koruyarak ve ihtiya├ž duydu─čunuzda s├╝rd├╝rmenize izin vererek ger├žekle┼čtirir.

─░lk fib arayarak ├ža─č─▒rd─▒─č─▒n─▒zda :

 f = fib()
 

Python i┼člevi derler, yield anahtar kelimeyle kar┼č─▒la┼č─▒r ve basit├že size geri bir jenerat├Âr nesnesi d├Ând├╝r├╝r. ├çok yard─▒mc─▒ de─čil g├Âr├╝n├╝yor.

Daha sonra talep etti─činizde, do─črudan veya dolayl─▒ olarak ilk de─čeri ├╝retti─činde, buldu─ču t├╝m ifadeleri a ile kar┼č─▒la┼č─▒ncaya kadar ├žal─▒┼čt─▒r─▒r yield , daha sonra sa─člad─▒─č─▒n─▒z de─čeri geri verir yield ve duraklat─▒r. Bunu daha iyi g├Âsteren bir ├Ârnek i├žin, baz─▒ print ├ža─čr─▒lar─▒ kullanal─▒m ( print "text" Python 2'deki ile de─či┼čtirin ):

 def yielder(value):
    """ This is an infinite generator. Only use next on it """ 
    while 1:
        print("I'm going to generate the value for you")
        print("Then I'll pause for a while")
        yield value
        print("Let's go through it again.")
 

┼×imdi REPL'e giriniz:

 >>> gen = yielder("Hello, yield!")
 

┼×imdi bir de─čer ├╝retmesi i├žin bir komut bekleyen bir jenerat├Âr nesnesine sahipsiniz. Kullan─▒n next ve nelerin bas─▒ld─▒─č─▒n─▒ g├Âr├╝n:

 >>> next(gen) # runs until it finds a yield
I'm going to generate the value for you
Then I'll pause for a while
'Hello, yield!'
 

Belirtilmemi┼č sonu├žlar, bas─▒lan sonu├žtur. Al─▒nt─▒lanan sonu├ž, geri d├Ând├╝r├╝len sonu├žtur yield . next ┼×imdi tekrar aray─▒n :

 >>> next(gen) # continues from yield and runs again
Let's go through it again.
I'm going to generate the value for you
Then I'll pause for a while
'Hello, yield!'
 

Jenerat├Âr duraklat─▒ld─▒─č─▒n─▒ hat─▒rlar yield value ve oradan devam eder. Bir sonraki mesaj yazd─▒r─▒l─▒r ve yield duraklat─▒lacak ifadenin aranmas─▒ tekrar ger├žekle┼čtirilir ( while d├Âng├╝ nedeniyle ).


33