Ano ang ginagawa ng keyword ng ani?

Ano ang paggamit ng keyword ng yield sa Python? Ano ang ginagawa nito?

Halimbawa, sinusubukan kong maunawaan ang code na ito 1 :

 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 

At ito ay isang dialer

 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 

Ano ang mangyayari kapag ang _get_child_candidates paraan? Nagbalik ang listahan? Single item? Tawag na muli? Kailan hihinto ang mga follow-up na tawag?


1. Ang code ay kinuha mula sa Jochen Schulz (jrschulz), na lumikha ng isang mahusay na library ng Python para sa mga puwang ng panukat. Ito ay isang link sa buong source: mspace Module

8911
ibinigay ni Alex. 24 окт. S. 24 oct. 2008-10-24 01:21 '08 at 1:21 am 2008-10-24 01:21
@ 46 sagot
  • 1
  • 2

Upang maunawaan kung anong yield , kai>

iterated

Kapag lumikha ka ng isang listahan, maaari mong basahin ang mga item nito nang isa-isa. Ang pagbasa ng mga elemento nito isa-isa ay tinatawag na isang pag-ulit:

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

repeatable ang mylist . Kapag ginamit mo ang listahan ng pag-unawa, lumikha ka ng isang listahan, at samakatuwid ay paulit-ulit:

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

Ang lahat ng maaari mong gamitin " for... in... " ay umuulit; lists , mga strings , mga file ...

Ang mga pag-ulit na ito ay maginhawa dahil maaari mong basahin ang mas maraming hangga't gusto mo, ngunit itinatago mo ang lahat ng mga halaga sa memorya, at hindi ito palaging kung ano ang gusto mo kapag mayroon kang maraming mga halaga.

Mga Generator

Ang mga generators ay mga iterators, isang uri ng pag-ulit na maaari mong ulitin nang isang beses lamang . Ang mga generator ay hindi nag-iimbak ng lahat ng mga halaga sa memorya; bumuo sila ng mga halaga sa fly :

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

Ito ay pareho, maliban na ginamit mo () halip ng [] . NGUNIT, hindi mo maaaring gawin for я in mygenerator pangalawang pagkakataon, dahil ang mga generators ay maaaring gamitin nang isang beses lamang: kinakalkula nila 0, pagkatapos ay kalimutan ang tungkol dito at kalkulahin ang 1, at magtapos ng pagkalkula 4, isa-isa.

Magbigay

yield ay isang keyword na ginagamit bi>return , maliban na ang function ay babalik sa isang generator.

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

Narito ang isang wa>

Upang makayanan ang yield , dapat mong maunawaan na kapag tumawag ka ng isang function, ang code na nakasulat sa katawan ng function ay hindi nagsisimula. Ang function ay nagbabalik lamang sa bagay ng generator, ito ay isang bit kumplikado :-)

Pagkatapos ay magpapatuloy ang iyong code mula sa kung saan ito umalis sa bawat oras, for paggamit ng generator.

Ngayon ang pinakamahirap na bahagi:

Sa unang pagkakataon na tumawag ka for tumawag sa isang generator na nilikha mula sa iyong function, patakbuhin ang code sa iyong function mula sa simula hanggang sa umabot sa yield , at pagkatapos ay babalik ang unang halaga ng loop. Pagkatapos, ang bawat kasunod na tawag ay magsisimula sa loop na isinulat mo muli sa pag-andar at ibalik ang susunod na halaga hanggang ang halaga ay ibinalik.

Ang generator ay itinuturing na wa>yield . Ito ay maaaring dahil sa ang katunayan na ang ikot ng panahon ay natapos na, o dahil sa ang katunayan na hindi mo na masisiyahan ang "if/else" .


Ipinaliwanag ang iyong code

Generator:

 # 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 

Subscriber:

 # 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 

Ang code na ito ay naglalaman ng i>

  • Ang pag-ikot ay paulit-ulit sa listahan, ngunit ang listahan ay nagpapalawak sa panahon ng pag-ulit ng loop :-) Ito ay isang maikling paraan upang mapuntahan ang lahat ng nested na data na ito, kahit na ito ay isang bit mapanganib, dahil maaari kang makakuha ng isang wa>candidates.extend(node._get_child_candidates(distance, min_dist, max_dist)) lahat ng mga halaga ng generator, ngunit while patuloy na lumikha ng mga bagong bagay sa generator na bubuo ng mga halaga maliban sa mga naunang, dahil hindi ito nalalapat sa parehong node .

  • Ang extend() method ay isang paraan ng isang listahan ng bagay na naghihintay para sa pag-ulit at nagdadagdag ng mga halaga nito sa listahan.

Karaniwan naming binibigyan siya ng isang listahan:

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

Ngunit sa iyong code nakakakuha ito ng isang generator, na kung saan ay mabuti, dahil:

  1. Hindi mo kai>
  2. Maaari kang magkaroon ng maraming mga anak, at ayaw mo si>

At ito ay gumagana dahil sa Python ay hindi pag-aalaga kung ang argument ng paraan ay isang listahan o hindi. Naghihintay ang sawa para sa pag-ulit, kaya gagana ito sa mga string, listahan, tuple, at generator! Ito ay tinatawag na pato at isa sa mga dahilan kung bakit napakaganda ng Python. Ngunit ito ay isa pang kuwento para sa isa pang tanong ...

Maaari kang tumigil dito o magbasa ng kaunti upang makita ang mga advanced na paggamit ng generator:

Pagkontrol ng pagkaubos ng generator

 >>> 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 ... 

Tandaan Para sa Python 3, gamitin ang print(corner_street_atm.__next__()) o i- print(next(corner_street_atm))

Maaari itong maging kapaki-pakinabang para sa iba't ibang mga bagay, tulad ng pagkontrol ng access sa isang mapagkukunan.

Itertools, ang iyong pinakamatalik na kaibigan

Ang module ng itertools ay naglalaman ng mga espesyal na pag-andar para sa pamamahala ng mga pag-ulit. Nais mo bang duplicate ang isang generator? Isang kadena ng dalawang generators? Mga halaga ng grupo sa isang nested na listahan na may isang linya? Map/Zip wa>

Pagkatapos ay i- import itertools .

Isang halimbawa? Tingnan natin ang mga posibleng pamamaraan ng pagdating para sa karera ng kabayo:

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

Pag-unawa sa mga mekanismo ng internal na pag-ulit

Ang pag-ulit ay isang proseso na nagpapahiwatig ng mga iteration (pagpapatupad ng __iter__() pamamaraan) at mga iterators (pagpapatupad ng __next__() paraan). Ang mga Iterations ay anumang mga bagay mula sa kung saan maaari kang makakuha ng iterator. Ang mga tagapamagitan ay mga bagay na nagbibigay-daan sa iyo upang ulitin ang mga pag-ulit.

Mayroong higit pa tungkol dito sa artikulong ito kung paano mag- loop ng trabaho .

13022
24 окт. Ang sagot ay ibinigay ng e-satis 24 oct. 2008-10-24 01:48 '08 at 1:48 2008-10-24 01:48

Lagyan ng label ang yield Grocking

Kapag nakakita ka ng isang function na may yield , gamitin ang simpleng lin>

  1. Ipasok ang result = [] sa simula ng function.
  2. Palitan ang bawat yield expr ang result.append(expr) .
  3. Ipasok ang resulta ng resulta ng return result line sa ilalim ng function.
  4. Yay - wala nang pahayag ng yield ! Basahin at alamin ang code.
  5. Ihambing ang function sa orihinal na kahulugan.

Ang pamamaraan na ito ay maaaring magbigay sa iyo ng isang ideya ng lohika ng isang function, ngunit kung ano talaga ang mangyayari sa isang yield ay makabuluhang naiiba mula sa kung ano ang mangyayari sa listahan-based na diskarte. Sa maraming mga kaso, ang paraan ng ani ay magiging mas mahusay at mas mabilis. Sa iba pang mga kaso, ang lansihin na ito ay makakakuha ng mapagmataas sa isang wa>

Huwag lituhin ang iyong mga iterators, iterators at generators.

Una, ang iterator protocol - kapag sumulat ka

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

Gumagana ang Python ang sumusunod na dalawang hakbang:

  1. Nakakakuha ng isang iterator para sa mylist :

    Ang pagtawag sa iter(mylist) → ay nagbabalik ng isang bagay sa next() paraan (o __next__() sa Python 3).

    [Ito ay isang hakbang na nalimutan ng karamihan ng tao na pag-usapan]

  2. Gumagamit ng isang iterator sa mga elemento ng loop:

    Magpatuloy sa pagtawag sa next() paraan sa iterator ibinalik mula sa hakbang 1. Ang return value na next() nakatalaga sa x at ang katawan ng loop ay pinaandar. Kung ang pagbubukod ng StopIteration tinatawag mula sa loob ng next() , nangangahulugan ito na wala nang mga halaga sa iterator at nagtatapos ang pag-ikot.

Ang katotohanan ay na ang Python ay gumaganap sa itaas ng dalawang mga hakbang sa anumang oras kapag ito ay nais na ulitin sa ibabaw ng mga nilalaman ng isang bagay - upang ito ay isang para sa loop, ngunit maaari rin itong code tulad ng otherlist.extend(mylist) (kung saan ang ibang otherlist ay isang listahan ng Python ),

border=0

Dito, ang mylist ay umuulit dahil ipinapatupad nito ang iterator protocol. Sa isang class na tinukoy ng user, maaari mong ipatupad ang __iter__() paraan upang gawin ang iyong mga klase sa pag- __iter__() . Ang pamamaraan na ito ay dapat ibalik ang isang iterator. Ang iterator ay isang bagay na may next() paraan. Maaari mong ipatupad ang parehong __iter__() at next() sa parehong klase at mayroong __iter__() nagbabalik sa self . Ito ay gagana para sa mga simpleng kaso, ngunit hindi kapag nais mo ng dalawang iterators na ikot ng parehong bagay sa parehong oras.

Kaya sa protocol iterator, maraming mga bagay ang nagpapatupad ng protocol na ito:

  1. Mga built-in na listahan, mga diksyunaryo, mga tuple, mga hanay, mga file.
  2. Mga pasadyang klase na nagpapatupad ng __iter__() .
  3. Mga Generator.

Tandaan na ang for loop ay hindi alam kung saan ang bagay na ito ay pakikitungo sa - ito ay sumusunod lamang sa iterator protocol at ay masaya na makakuha ng elemento sa pamamagitan ng elemento kapag ang pagtawag sa next() . Ang mga built-in na listahan ay ibabalik ang kani>yield :

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

Sa halip ng yield , kung may tatlong return f123() operator sa f123() tanging ang una, at ang f123() function. Ngunit ang f123() hindi isang pangkaraniwang function. Kapag f123() , wala itong halaga sa mga pahayag ng ani! Ibinabalik ang generator object. Bi>for loop na pagtatangka upang loop ang generator object, ang function ay bumalik mula sa kanyang naka-pause na estado sa susunod na linya pagkatapos ng naunang ibinalik resulta yield , executes ang susunod na linya ng code, sa kasong ito ang yield , at ibalik ito bi>StopIteration generator at ang StopIteration cycle.

Kaya, ang generator object ay pareho sa isang adaptor - sa isang dulo ito nagpapakita ng isang iterator protocol, na nagbibigay ng __iter__() at next() upang mapanatili ang isang for loop sa mabuting kalagayan. Gayunpaman, sa kabi>

Bakit gumagamit ng mga generator?

Maaari mong karaniwang isulat ang code na hindi gumagamit ng generators, ngunit nagpapatupad ng parehong lohika. Ang isang pagpipilian ay ang paggamit ng pansamanta>SomethingIter na nagse-save ng estado sa mga elemento ng pagkakataon at nagsasagawa ng susunod na lohikal na hakbang dito sa pamamagitan ng next() paraan (o __next__() sa Python 3). Depende sa lohika, ang code sa loob ng next() paraan ay maaaring tumingin sobrang kumplikado at madaling kapitan ng sakit sa mga error. Narito ang mga generators na nagbibigay ng malinis at simpleng solusyon.

1744
26 окт. sagot na ibinigay ng user28409 Oktubre 26 2008-10-26 00:22 '08 at 0:22 2008-10-26 00:22

Isipin ito tulad nito:

Isang iterator ay isang magarbong term para sa isang bagay na may kasunod na () paraan. Kaya, ang pag-andar sa pag-abot sa huli ay ganito ang hitsura nito:

Orihinal na bersyon:

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

Ito ay karaniwang kung ano ang ginagawa ng interpreter ng Python sa code sa itaas:

 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 

Upang mas mahusay na maunawaan kung ano ang nangyayari sa likod ng mga eksena, ang for loop ay maaaring muling isinulat bi>

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

Gumagawa ba ito ng higit na kahulugan o nakalilito lamang sa iyo? :)

Dapat kong ituro na ito ay isang pagpapadali para sa mga layuning pang-ilustrasyon. :)

441
24 окт. Sumagot kay Jason Baker sa Oktubre 24 2008-10-24 01:28 '08 at 1:28 2008-10-24 01:28

Ang keyword ng yield bumaba sa dalawang simpleng katotohanan:

  1. Kung nakikita ng tagatala ang keyword ng yield saanman sa loob ng isang function, ang function na ito ay hindi na ibabalik sa pamamagitan ng return . Sa halip, ito ay agad na nagbabalik ng isang tamad na bagay ng listahan ng paghihintay, na tinatawag na isang generator.
  2. Ang generator ay paulit-ulit. Ano ang repeatable? Ito ay isang list set range o dict-view na may naka-embed na protocol para sa pagbisita sa bawat item sa isang partikular na order.

Sa maikling salita: ang isang dyeneretor ay isang tamad, dahan-dahan na pagtaas ng listahan , at ang yield nagpapahintulot sa iyo na gamitin ang function na notasyon upang programa ang mga halaga ng listahan na dahan-dahan ang generator ay dapat na output.

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

isang halimbawa

Tukuyin natin ang function makeRange na katulad ng range Python. Ang makeRange(n) tawag ay makeRange(n) GENERATOR:

 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> 

Upang gawing kaagad na ibalik ng generator ang mga nakabinbing halaga, maaari mong ipasa ito sa list() (tulad ng anumang pag-uulit):

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

Paghahambing ng isang halimbawa sa "pagbabalik >

Ang halimbawa sa itaas ay maaaring makita bi>

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

Gayunpaman, mayroong isang makabuluhang pagkakaiba; Tingnan ang huling seksyon.


Paano mo magagamit ang mga generator

Iterated ang huling bahagi ng pag-unawa sa listahan, at ang lahat ng mga generator ay umuulit, kaya madalas itong ginagamit tulad nito:

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

Upang mas mahusay na maunawaan ang mga generators, maaari kang maglaro sa itertools ang module na itertools (siguraduhin na gamitin chain.from_iterable at hindi chain may warranty para sa chain.from_iterable ). Halimbawa, maaari mo ring gamitin ang mga generator upang maipatupad ang wa>itertools.count() . Maaari mong ipatupad ang iyong sariling def enumerate(iterable): zip(count(), iterable) o, def enumerate(iterable): zip(count(), iterable) kahalili, gawin ito gamit ang keyword ng yield sa isang habang loop.

Tandaan na ang mga generators ay maaaring gamitin para sa maraming iba pang mga layunin, tulad ng pagpapatupad ng coroutines, di-deterministic programming, o iba pang mga eleganteng bagay. Gayunpaman, ang view ng "tamad na listahan", na kinakatawan ko rito, ay ang pinakakaraniwang lugar ng paggamit na makikita mo.


Sa likod ng mga eksena

Ito ay kung paano gumagana ang Python Iteration Protocol. Iyan ang nangyayari kapag gumawa ka ng list(makeRange(5)) . Ito ang inilalarawan ko nang mas maaga bi>

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

Ang next() built-in function ay tawag lamang .next() bagay .next() , na bahagi ng "protocol na pag-ulit" at nangyayari sa lahat ng mga iterators. Maaari mong manwal na gamitin ang next() function (at iba pang mga bahagi ng pag-ulit protocol) upang ipatupad ang mga hindi pangkaraniwang bagay, karaniwan sa gastos ng pagiging madaling mabasa, kaya subukang huwag gawin ito ...


maliit na bagay

Kadalasan, ang karamihan sa tao ay hindi nagmamalasakit sa mga sumusunod na pagkakaiba at malamang na nais na pigilan ang pagbabasa dito.

Sa Python, umuulit ang anumang bagay na "nauunawaan ang konsepto ng isang para sa loop", halimbawa, isang listahan [1,2,3] , at isang iterator ay isang partikular na halimbawa ng hiniling para sa loop, halimbawa [1,2,3].__iter__() . Ang generator ay eksaktong kapareho ng anumang iterator, maliban sa paraan ng pagkakasulat nito (na may syntax ng function).

Kapag humiling ka ng isang iterator mula sa listahan, lumilikha ito ng isang bagong tagalipat. Gayunpaman, kapag humiling ka ng isang iterator mula sa isang iterator (na bihirang ginagawa mo), binibigyan ka nito ng kopya nito.

Kaya sa hindi malamang pangyayari na hindi mo magawa ang isang bagay na katulad nito ...

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

... pagkatapos ay tandaan na ang generator ay isang iterator; i.e. isang beses gamitin. Kung nais mong muling gamitin ito, dapat mong myRange(...) ang myRange(...) myRange(...) . Kung kai>x = list(myRange(5)) . Ang mga wa>itertools.tee kung kinakai>PEP na nag- aalok para sa iterator ay naantala.

378
19 июня '11 в 9:33 2011-06-19 09:33 ang sagot ay ibinigay ninjagecko Hunyo 19 '11 sa 9:33 2011-06-19 09:33

Ano ang ginagawa ng keyword ng yield sa python?

Response Scheme / Summary

  • Ang function ng yield sa tawag ay nagbabalik ng generator .
  • Ang mga generator ay iterators dahil pinapatupad nila ang isang iterator protocol , upang maaari mong ulitin ang mga ito.
  • Ang impormasyon ay maaari ring ipadala sa generator, na ginagawa itong conceptually isang coroutine .
  • Sa Python 3, maaari mong ipagkaloob mula sa isang generator patungo sa isa pa sa parehong direksyon gamit ang yield from .
  • (Приложение критикует пару @, включая верхний, и обсуждает использование return в генераторе.)

Генераторы:

yield допустим только внутри определения функции, и включение yield в определение функции заставляет его возвращать генератор.

Идея для генераторов исходит из других языков (см. Сноску 1) с различными реализациями. В Python Generators выполнение кода заморожено в точке выхода. Когда вызывается генератор (методы обсуждаются ниже), выполнение возобновляется, а затем останавливается при следующем выходе.

yield предоставляет простой способ реализации протокола итератора , который определяется следующими двумя методами: __iter__ и next (Python 2) или __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.