Hızlı anahtar kelime ne işe yarar?

Python'da yield anahtar sözcüğünün kullanımı nedir? 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 bir çevirici

 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 

_get_child_candidates yöntemi ne olur? Liste geri döndü mü? Tek ürün? Yine mi arandı? Takip çağrıları ne zaman sona erecek?


1. Kod, metrik uzaylar için mükemmel bir Python kütüphanesi oluşturan Jochen Schulz'dan (jrschulz) alınmıştır. Bu tam kaynağa bir link: mspace Modülü .

8911
Alex tarafından verildi . 24 окт. S. 24 ek. 2008-10-24 01:21 '08, 01:21 - 2008-10-24 01:21
@ 46 cevaplar
  • 1
  • 2

Bir yield ne olduğunu anlamak için, jeneratörlerin ne olduğunu anlamanız gerekir. Ve jeneratörler, tekrarlayıcılar gelmeden önce.

Iterables

Bir liste oluşturduğunuzda, öğelerini tek tek okuyabilirsiniz. Öğelerini tek tek okumak yineleme olarak adlandırılır:

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

mylist tekrarlanabilir. Liste anlama özelliğini kullandığınızda, bir liste oluşturursunuz ve bu nedenle tekrarlanabilir:

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

" for... in... " for... in... kullanabileceğiniz tek şey yinelemelidir; lists , strings , dosyalar ...

Bu yinelemeler kullanışlıdır, çünkü istediğiniz kadar okuyabilirsiniz, ancak tüm değerleri hafızada tutarsınız ve bu her zaman istediğiniz gibi olmaz.

jeneratörler

Jeneratörler yineleyicilerdir, yalnızca bir kez tekrarlayabileceğiniz bir yineleme türüdür. Jeneratörler tüm değerleri hafızada tutmazlar, anında değerleri üretirler :

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

Bu, [] yerine () kullanmanız dışında aynı. Ancak, jeneratörler içinde ikinci kez for я in mygenerator , çünkü jeneratörler yalnızca bir kez kullanılabilirler: 0'ı hesaplarlar, sonra unuturlar ve 1'i hesaplarlar ve 4'ü birbiri ardına hesaplarlar.

vermek

yield , işlevin bir jeneratör döndürmesi dışında, return olarak 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.

yield ile başa çıkmak için, bir işlev çağırdığınızda, işlev gövdesinde yazılı olan kodun başlayamadığını anlamalısınız . İşlev, yalnızca jeneratör nesnesini döndürür, biraz karmaşıktır :-)

Sonra kodunuz, jeneratörü kullanmak için her defasında kaldığı yerden devam edecektir.

Şimdi en zor kısım:

İlk aradığınızda for fonksiyonunuzdan yaratılmış bir jeneratör nesnesini çağırır, fonksiyonunuzdaki kodu en baştan yield ulaşana kadar çalıştırır ve ardından döngünün ilk değerini döndürür. Ardından, sonraki her çağrı, işleve yazdığınız döngüyü yeniden başlatır ve değer döndürülene kadar bir sonraki değeri döndürür.

İşlev başlatıldıktan sonra jeneratör boş sayılır, ancak artık yield . Bu, döngünün sona ermesi veya "if/else" artık karşılamadığınızdan dolayı "if/else" .


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 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 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 candidates 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ı bölüm içeriyor:

  • Döngü listede tekrarlanır, ancak liste döngü yinelemesi sırasında genişler :-) Bu, sonsuz bir döngü elde edebileceğiniz için, biraz tehlikeli olsa bile, tüm bu iç içe geçmiş verileri gözden geçirmenin kısa bir yoludur. Bu durumda, candidates.extend(node._get_child_candidates(distance, min_dist, max_dist)) tüm jeneratör değerlerini tüketir, ancak aynı düğüm için geçerli olmadığından, öncekilerden farklı değerler üretecek yeni jeneratör nesneleri oluşturmaya devam eder. .

  • extend() yöntemi, yinelemeyi bekleyen ve değerlerini listeye ekleyen bir liste nesnesinin bir yöntemidir.

Genellikle ona bir liste veririz:

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

Ancak kodunuzda iyi olan bir jeneratör alır, çünkü:

  1. Değerleri iki kez okumanıza gerek yoktur.
  2. Çok fazla çocuğunuz olabilir ve hepsinin hafızada tutulmasını istemiyorsunuz.

Ve işe yarıyor çünkü Python metodun argümanının bir liste olup olmadığına aldırmıyor. Python yinelemeyi bekliyor, bu yüzden dizelerle, listelerle, totelerle ve jeneratörlerle çalışacak! Buna ördek denir ve Python'un bu kadar harika olmasının sebeplerinden biridir. Ama bu başka bir soru için başka bir hikaye ...

Jeneratörün gelişmiş kullanımını görmek için burada durdurabilir veya biraz okuyabilirsiniz:

Jeneratör tükenme kontrolü

 >>> class Bank(): # Let create a bank, building ATMs ... crisis = False ... def create_atm(self): ... while not self.crisis: ... yield "$100" >>> hsbc = Bank() # When everything 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 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))

Bu, bir kaynağa erişimi kontrol etmek gibi çeşitli şeyler için faydalı olabilir.

İtertools, en iyi arkadaşın

İtertools modülü yinelemeleri yönetmek için özel fonksiyonlar içerir. Hiç bir jeneratörü çoğaltmak istediniz mi? İki jeneratör zinciri mi? Yuvalanmış bir listede tek satırlı grup değerleri? Başka bir liste oluşturmadan Map/Zip ?

O zaman sadece import itertools .

Bir örnek? At yarışı için olası varış prosedürlerine bir göz atalım:

 >>> 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)] 

İç yineleme mekanizmalarını anlama

Yineleme, yinelemeleri ( __iter__() yöntemini uygulayarak) ve yineleyicileri ( __next__() yöntemini uygulayarak) içeren bir __next__() . Yinelemeler, yinelemeci alabileceğiniz nesnelerdir. Yineleyiciler yinelemeleri tekrarlamanıza izin veren nesnelerdir.

Bu konuda daha fazla döngü var nasıl çalıştığını hakkında .

13022
24 окт. Cevap e-satis 24 oct tarafından verilmiştir . 2008-10-24 01:48 '08, 1:48 2008-10-24 01:48

Oluk yield etiket

yield olan bir işlev gördüğünüzde, ne olacağını anlamak için bu basit numarayı kullanın:

  1. Fonksiyonun başına result = [] yerleştirin.
  2. Expr'nin her yield expr result.append(expr) ile değiştirin.
  3. İşlev return result satırının sonucunu yerleştirin.
  4. Yay - artık yield beyanı yok! Kodu okuyup bulun.
  5. Fonksiyonu orijinal tanımla karşılaştırın.

Bu teknik size bir fonksiyonun mantığı hakkında bir fikir verebilir, ancak gerçekte bir yield gerçekleşenler liste temelli yaklaşımda olanlardan önemli ölçüde farklıdır. Çoğu durumda, verim yaklaşımı çok daha verimli ve daha hızlı olacaktır. Diğer durumlarda, orijinal numara düzgün çalışsa bile, bu numara sonsuz bir döngüde sıkışıp kalacak. Daha fazlasını öğrenmek için okumaya devam edin ...

Yineleyicilerinizi, yineleyicilerinizi ve jeneratörlerinizi 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. mylist için bir yineleyici alır:

    iter(mylist)__next__() , bir next() yöntemiyle (veya Python 3'te __next__() bir nesne döndürür.

    [Bu, çoğu insanın konuşmayı unuttuğu bir adımdır]

  2. Öğeleri döngülemek için bir yineleyici kullanır:

    Yineleyicideki next() yöntemini çağırmaya devam edin, adım 1'den döndürülür. Next next() dönüş değeri x atanır ve döngünün gövdesi yürütülür. StopIteration özel StopIteration next() içinden çağrılırsa, StopIteration başka değer olmadığı ve döngü sona erdiği anlamına gelir.

Gerçek şu ki, Python, bir nesnenin içeriğini yinelemek istediğinde herhangi bir zamanda yukarıdaki iki adımı gerçekleştirir - yani bu bir for döngüsü olabilir, ancak otherlist.extend(mylist) gibi bir kod olabilir (diğer listenin bir Python listesi olduğu )

border=0

Burada, mylist yineleyici protokolünü uyguladığı için yineleyicidir. Kullanıcı tanımlı bir sınıfta, sınıf örneklerinizi yinelemek için __iter__() yöntemini uygulayabilirsiniz. Bu yöntem bir yineleyici döndürmelidir. Bir yineleyici, next() yöntemine sahip bir nesnedir. Hem __iter__() hem de next() 'yi aynı sınıfa __iter__() ve __iter__() self dönmesini __iter__() . Bu basit durumlar için işe yarar, ancak iki yineleyicinin aynı nesneyi aynı anda döngülendirmesini istediğinizde çalışmaz.

Böylece yineleyici protokolünde birçok nesne bu protokolü uygular:

  1. Yerleşik listeler, sözlükler, dosyalar, kümeler, dosyalar.
  2. __iter__() uygulayan özel sınıflar.
  3. Jeneratörler.

for döngüsünün hangi nesneyle uğraştığını bilmediğini unutmayın - sadece yineleyici protokolünü izler ve next() işlevini çağırırken öğeye göre eleman almaktan mutluluk duyar. Yerleşik listeler öğelerini birer birer döndürür, sözlükler anahtarları birer birer döndürür, dosyalar birer birer dizeler döndürür vb. Ve jeneratörler geri döner ... peki, yield geldiğinde:

 def f123(): yield 1 yield 2 yield 3 for item in f123(): print item 

yield yerine, f123() üç return f123() operatörü f123() yalnızca birincisi ve f123() işlevi. Fakat f123() sıradan bir fonksiyon değildir. f123() , verim ifadelerinde hiçbir değer döndürülmez! Bir jeneratör nesnesini döndürür. Buna ek olarak, işlev aslında ortaya çıkmaz - bir bekleme durumuna girer. for döngüsü, jeneratör nesnesini döngülemeye çalıştığında, işlev daha önce döndürülen sonuç yield ardından bir sonraki satırda duraklatılmış durumundan geri döner, bir sonraki kod satırını yürütür, bu durumda yield ve onu bir sonraki öğe olarak döndürür. Bu işlev serbest bırakılıncaya kadar ve şu anda StopIteration üreteci ve StopIteration çevrimi gerçekleşir.

Bu nedenle, jeneratör nesnesi bir adaptöre benzer - bir uçta bir for döngüsü iyi durumda tutmak for __iter__() ve next() sağlayan bir yineleyici protokolü gösterir. Öte yandan, bir sonraki değeri elde etmek için yeterli bir işlevi başlatır ve tekrar bekleme moduna geçirir.

Neden jeneratör kullanıyorsunuz?

Genellikle jeneratör kullanmayan ancak aynı mantığı uygulayan kod yazabilirsiniz. Bir seçenek daha önce bahsettiğim geçici numara listesini kullanmaktır. Bu, örneğin sonsuz döngüleriniz varsa veya çok uzun bir listeniz olduğunda hafızanın verimsiz kullanılmasına yol açabilirse, her durumda işe yaramayacaktır. Başka bir yaklaşım, durumu örnek öğelerinde kaydeden ve içindeki bir sonraki mantıksal adımı next() yöntemiyle (veya Python 3'te __next__() gerçekleştiren yeni yinelemeli sınıfı SomethingIter sınıfını uygulamaktır. Mantığa bağlı olarak, next() yönteminin içindeki kod çok karmaşık görünebilir ve hatalara açık olabilir. Burada jeneratörler temiz ve basit bir çözüm sunar.

1744
26 окт. Tarafından verilen cevap user28409 26 Eki 2008-10-26 00:22 '08, 0:22 2008-10-26 00:22

Bunun gibi düşünün:

Bir yineleyici, bir next () yöntemine sahip bir nesne için yalnızca süslü bir terimdir. Böylece, verim ed işlevi sonuçta şöyle görünür:

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 

Sahnelerin arkasında neler olduğunu daha iyi anlamak for , for döngüsü aşağıdaki gibi yeniden yazılabilir:

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

Daha mantıklı mı yoksa sadece kafan mı karıştı? :)

Bunun açıklama amaçlı bir basitleştirme olduğunu belirtmeliyim. :)

441
24 окт. 24 Ekim tarihinde Jason Baker Cevapla 2008-10-24 01:28 '08, 1:28 2008-10-24 01:28

yield anahtar sözcüğü iki basit gerçeğe dayanır:

  1. Derleyici bir işlevin herhangi bir yerinde yield anahtar sözcüğünü algılarsa, bu işlev artık return döndürülmez. Bunun yerine, derhal bir jeneratör adlı tembel bir bekleme listesi nesnesini döndürür.
  2. Jeneratör tekrar edildi. Tekrarlanabilir nedir? Bu, her bir öğeyi belirli bir sırayla ziyaret etmek için yerleşik bir protokol içeren bir list set range veya dict-view gibi bir şeydir.

Özetle: bir jeneratör tembel, kademeli olarak artan bir listedir ve yield , üretecin kademeli olarak çıkarması gereken liste değerlerini programlamak için gösterim fonksiyonunu 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]] 

bir örnek

Python range benzer olan makeRange işlevini tanımlayalım. makeRange(n) çağrısı JENERATÖRÜ makeRange(n) :

 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ün hemen beklemedeki değerleri döndürmesini sağlamak için, list() geçirebilirsiniz (yinelemeli herhangi biri gibi):

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

Bir örneği "sadece listeyi döndürmek" ile karşılaştırmak

Yukarıdaki örnek, basitçe eklediğiniz ve iade ettiğiniz bir liste oluştururken görü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] 

Ancak, önemli bir fark var; Son bölüme bakınız.


Jeneratörleri nasıl kullanabilirsiniz?

Yinelenen listeyi anlamanın son kısmıdır ve tüm üreticiler yinelemelidir, bu nedenle sık sık böyle kullanılır:

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

Jeneratörleri daha iyi anlamak için, itertools modülüyle oynayabilirsiniz ( chain.from_iterable ve chain.from_iterable için bir garanti ile chain kullanmadığınızdan emin olun). Örneğin, jeneratörler bile itertools.count() gibi sonsuz uzun tembel listeler uygulamak için kullanabilirsiniz. Kendi def enumerate(iterable): zip(count(), iterable) veya alternatif olarak bunu bir while döngüsü içinde yield anahtar sözcüğünü kullanarak yapabilirsiniz.

Üreticilerin koroinler uygulamak, deterministik olmayan programlama veya diğer zarif şeyler gibi birçok başka amaç için kullanılabileceğini unutmayın. Ancak, burada temsil ettiğim “tembel listeler” görünümü, bulacağınız en yaygın kullanım alanı.


Perde arkasında

Python Yineleme Protokolü böyle çalışır. Bir list(makeRange(5)) yaptığınızda ne olur list(makeRange(5)) . Bu daha önce "tembel, fazladan 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 

.next() next() yerleşik işlevi sadece "yineleme protokolünün" bir parçası olan ve tüm yineleyicilerde oluşan .next() nesnelerini .next() çağırır. Olağandışı şeyleri (genellikle okunabilirlik pahasına) uygulamak için next() işlevini (ve yineleme protokolünün diğer bölümlerini next() el ile kullanabilirsiniz, bu yüzden bunu yapmamaya çalışın ...


küçük şeyler

Genellikle, çoğu insan aşağıdaki farklılıkları önemsemez ve muhtemelen burada okumayı bırakmak isteyecektir.

Python'da, yinelemeli "for döngüsü kavramını anlayan" herhangi bir nesne, örneğin, bir liste [1,2,3] ve bir yineleyici, döngü için istenen örneğin belirli bir örneğidir, örneğin [1,2,3].__iter__() . Jeneratör, yazılma şekli dışında (fonksiyonun sözdizimi ile), herhangi bir yineleyici ile tamamen aynıdır.

Listeden bir yineleyici istediğinde, yeni bir yineleyici oluşturur. Bununla birlikte, bir yineleyiciden (nadiren yaptığınız) bir yineleyici isteğinde bulunduğunuzda, bu yalnızca size bir kopyasını verir.

Bu yüzden olası bir olayda böyle bir şey yapamazsınız ...

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

... o zaman jeneratörün bir yineleyici olduğunu unutmayın; yani bir kerelik kullanım. Yeniden kullanmak istiyorsanız, myRange(...) çağırmalısınız. x = list(myRange(5)) iki kez kullanmanız gerekirse, sonucu bir listeye dönüştürün ve bunu x = list(myRange(5)) değişkenine kaydedin x = list(myRange(5)) . Bir jeneratörü kesinlikle klonlamak isteyenler (örneğin, korkunç hacker metaprogramming yapanlar) , yineleyici için itertools.tee Python PEP standartları geciktiğinden, kesinlikle gerekliyse, itertools.tee kullanabilirsiniz.

378
19 июня '11 в 9:33 2011-06-19 09:33 Cevap 19 haziran 19: 9'da 9:33 2011-06-19 09:33

yield anahtar sözcüğü python'da ne yapar?

Yanıt Şeması / Özet

  • Çağrıda yield işlevi bir jeneratör döndürür.
  • Jeneratörler yineleyicilerdir, çünkü yineleyici protokolü uygularlar , böylece bunların üzerinde yineleme yapabilirsiniz.
  • Bilgi , aynı zamanda bir coroutine dönüştürülmesi için jeneratöre de gönderilebilir .
  • Python 3'te, yield from kullanarak her iki yönde bir jeneratörden diğerine delege edebilirsiniz.
  • (Uygulama, en tepesi de dahil olmak üzere birkaç yanıtı eleştirir ve jeneratörde return kullanımını tartışır.)

jeneratörleri:

yield yalnızca bir işlev tanımına izin verilir ve bir işlev tanımına bir yield dahil edilmesi, bunun bir jeneratör döndürmesine neden olur.

Jeneratörler için fikir, farklı uygulamalara sahip diğer dillerden (bkz. Dipnot 1). Python Generator'de, kod çalıştırma çıkış noktasında donar . Bir jeneratör çağrıldığında (yöntemler aşağıda tartışılmıştır), yürütme devam eder ve bir sonraki çıkışta durur.

yield , aşağıdaki iki yöntemle tanımlanan bir yineleyici protokolünü uygulamak için kolay bir yol sağlar: __iter__ ve next (Python 2) veya __next__ (Python 3). Оба эти метода делают объект итератором, который можно проверить типом с помощью абстрактного базового класса Iterator из модуля 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 an iterable True >>> hasattr(gen, 'next') # and with .next (.__next__ in Python 3) True # implements the iterator protocol.