Kaip pasirinkti vieną elementą iš generatoriaus (pythone)?

Turiu generatoriaus funkciją, pavyzdžiui:

 def myfunct(): ... yield result 

Įprasta šio skambinimo funkcija yra:

 for r in myfunct(): dostuff(r) 

Mano klausimas yra, ar yra būdas gauti tik vieną elementą iš generatoriaus, kai man patinka? Pavyzdžiui, norėčiau padaryti kažką panašaus:

 while True: ... if something: my_element = pick_just_one_element(myfunct()) dostuff(my_element) ... 
105
20 янв. Alexandros yra nustatytas sausio 20 d 2011-01-20 00:55 '11 prie 0:55 2011-01-20 00:55
@ 5 atsakymai

Sukurkite generatorių naudojant

 g = myfunct() 

Kiekvieną kartą, kai norite naudoti elementą, naudokite

 g.next() 

arba

 next(g) 

Jei generatorius palieka, jis padidins „ StopIteration . Jei reikia, galite nuimti šią išimtį arba naudoti default argumentą next() :

 next(g, default_value) 
153
20 янв. Sven Marnach atsakė sausio 20 d 2011-01-20 00:58 '11 prie 0:58 2011-01-20 00:58

Norėdami pasirinkti tik vieną generatoriaus elementą, naudokite break , skirtą „ for arba „ list(itertools.islice(gen, 1)) išraiškai list(itertools.islice(gen, 1))

Pagal jūsų pavyzdį (tiesiogine prasme) galite tai padaryti:

 while True: ... if something: for my_element in myfunct(): dostuff(my_element) break else: do_generator_empty() 

Jei norite "gauti tik vieną elementą iš generatoriaus [kai sukurta], kai man tai patinka" (manau, kad 50% yra pirminis tikslas ir dažniausias ketinimas):

 gen = myfunct() while True: ... if something: for my_element in gen: dostuff(my_element) break else: do_generator_empty() 

Tokiu būdu galima išvengti aiškaus generator.next() Naudojimo ir I / O apdorojimas nereikalauja (kritinio) StopIteration išimties tvarkymo arba papildomų numatytų verčių palyginimų.

border=0

Kita else: iš punkto yra būtina tik tuo atveju, jei norite padaryti kažką ypatingo generatoriaus galo atveju.

Pastaba next() / .next() :

„Python3“ .next() metodas buvo pervadintas į .__next__() dėl geros priežasties: jos žemo lygio (PEP 3114). Prieš Python 2.6, next() integruota funkcija neegzistavo. Ir netgi buvo diskutuojama, kad next() judėti į operator modulį (kuris būtų pagrįstas) dėl jo retos būtinybės ir abejotinos infliacijos įterptųjų vardų.

next() pagal nutylėjimą vis dar yra labai žemo lygio praktika - atvirai mesti StopIteration kaip varžtą iš mėlynos į įprastą taikymo kodą. Ir naudodami next() su numatytąją vertę - tai turėtų būti geriausia vienintelė parinktis next() tiesiogiai builtins - ribota ir dažnai sukelia nelyginę ne-pyphonic logiką / skaitymą.

Apatinė eilutė: Kitų () naudojimas turėtų būti labai reti - pavyzdžiui, naudojant operator modulio funkcijas. Naudojant for x in iterator , islice , list(iterator) ir kitose sklandžiai atliekamose funkcijose yra natūralus būdas naudoti iteratorius taikomųjų programų lygiu - ir gana galbūt. next() yra žemo lygio, papildoma koncepcija, kuri nėra akivaizdi - kaip parodė klausimas apie šią temą. Nors, pavyzdžiui, break for yra visuotinai priimtas.

10
12 февр. Atsakymas pateikiamas kxr 12 vasario mėn. 2016-02-12 21:48 '16 at 21:48 2016-02-12 21:48

Nemanau, kad yra patogus būdas gauti generatoriaus savavališką vertę. Generatorius pateikia toliau nurodytą () metodą judėjimui, tačiau visa seka nėra sukurta nedelsiant, kad būtų išsaugota atmintis. Tai yra funkcinis skirtumas tarp generatoriaus ir sąrašo.

2
20 янв. atsakymą pateikė gddc sausio 20 2011-01-20 00:59 '11 prie 0:59 2011-01-20 00:59
 generator = myfunct() while True: my_element = generator.next() 

Būtinai užfiksuokite po paskutinio elemento sukurtą išimtį.

0
20 янв. atsakymą pateikė Jonas 20 d. 2011-01-20 01:01 '11 prie 1:01 2011-01-20 01:01

Manau, kad vienintelis būdas yra gauti sąrašą iš iteratoriaus ir tada gauti elementą iš šio sąrašo.

 l = list(myfunct()) l[4] 
-1
20 янв. atsakymas, kurį pateikė keegan3d sausio 20 d 2011-01-20 00:58 '11 prie 0:58 2011-01-20 00:58

Kiti klausimai apie žymes arba Užduoti klausimą