enumerate () - membuat generator dengan Python

90

Saya ingin tahu apa yang terjadi ketika saya meneruskan hasil dari fungsi generator ke enumerate () python. Contoh:

def veryBigHello():
    i = 0
    while i < 10000000:
        i += 1
        yield "hello"

numbered = enumerate(veryBigHello())
for i, word in numbered:
    print i, word

Apakah pencacahan diulangi dengan malas, atau apakah itu menyeruput semuanya menjadi yang pertama? Saya 99,999% yakin itu malas, jadi dapatkah saya memperlakukannya persis sama dengan fungsi generator, atau apakah saya perlu berhati-hati?

Adam
sumber
1
Saya kira Anda bermaksud menaikkan saya di veryBigHello.
robert
@robert: jika saya tidak salah saya secara otomatis meningkat
the_drow
@ the_drow Tidak dalam veryBigHellofungsi itu sendiri.
Will McCutchen
1
@ Akan: Oh, benar. Tapi itu hanya rewel. Itu sebuah contoh. Tetap diperbaiki.
the_drow

Jawaban:

108

Itu malas. Cukup mudah untuk membuktikan bahwa itu masalahnya:

>>> def abc():
...     letters = ['a','b','c']
...     for letter in letters:
...         print letter
...         yield letter
...
>>> numbered = enumerate(abc())
>>> for i, word in numbered:
...     print i, word
...
a
0 a
b
1 b
c
2 c
Dave Webb
sumber
Apakah ini Python 2 atau 3 (atau keduanya)? Apakah malas di keduanya? Saya diuji pada Python 2 dan itu adalah malas.
becko
2
Saya menguji ini pada Python 3.5.2, dan mengevaluasi dengan malas.
gobernador
42

Bahkan lebih mudah untuk membedakannya daripada salah satu dari saran sebelumnya:

$ python
Python 2.5.5 (r255:77872, Mar 15 2010, 00:43:13)
[GCC 4.3.4 20090804 (release) 1] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> abc = (letter for letter in 'abc')
>>> abc
<generator object at 0x7ff29d8c>
>>> numbered = enumerate(abc)
>>> numbered
<enumerate object at 0x7ff29e2c>

Jika enumerate tidak melakukan evaluasi malas itu akan mengembalikan [(0,'a'), (1,'b'), (2,'c')]atau beberapa (hampir) setara.

Tentu saja, enumerate hanyalah generator mewah:

def myenumerate(iterable):
   count = 0
   for _ in iterable:
      yield (count, _)
      count += 1

for i, val in myenumerate((letter for letter in 'abc')):
    print i, val
Wayne Werner
sumber
2
Terima kasih atas penjelasannya. Saya mengalami sedikit kesulitan untuk mencari tahu jawaban yang diterima. Setidaknya sampai aku melihat milikmu.
trendsetter37
13

Karena Anda dapat memanggil fungsi ini tanpa keluar dari pengecualian memori, fungsi ini jelas malas

def veryBigHello():
    i = 0
    while i < 1000000000000000000000000000:
        yield "hello"

numbered = enumerate(veryBigHello())
for i, word in numbered:
    print i, word
Nikolaus Gradwohl
sumber
0

Alternatif jadul karena saya menggunakan generator yang ditulis orang lain (sklearn) yang tidak berfungsi dengan pendekatan di sini.

i=(-1)
for x in some_generator:
    i+=1
HashRocketSyntax
sumber