enumerate () - ing một trình tạo trong Python


88

Tôi muốn biết điều gì sẽ xảy ra khi tôi chuyển kết quả của một hàm trình tạo cho python's enumerate (). Thí dụ:

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

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

Việc liệt kê có được lặp lại một cách lười biếng hay nó dồn mọi thứ vào đầu tiên? Tôi chắc chắn 99,999% là nó lười biếng, vậy tôi có thể xử lý nó giống hệt như chức năng của máy phát điện không, hay tôi có cần phải để ý gì không?


1
Tôi cho rằng bạn muốn tăng tôi trong VeryBigHello.
robert

@robert: nếu tôi không nhầm thì tôi tự động được tăng
the_drow

@the_drow Không có trong veryBigHellochính hàm.
Will McCutchen

1
@Will: Ồ, chính xác. Nhưng đó chỉ là nitpicking. Đó là một ví dụ. Vẫn cố định.
the_drow

Câu trả lời:


103

Nó lười biếng. Khá dễ dàng để chứng minh đó là trường hợp:

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

Đây là Python 2 hay 3 (hoặc cả hai)? Có phải là lười biếng trong cả hai? Tôi đã thử nghiệm trên Python 2 và nó khá lười biếng.
becko

2
Tôi đã thử nghiệm điều này trên Python 3.5.2 và nó đánh giá một cách lười biếng.
gobernador

42

Nó thậm chí còn dễ nói hơn một trong hai gợi ý trước đó:

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

Nếu liệt kê không thực hiện đánh giá lười biếng, nó sẽ trả về [(0,'a'), (1,'b'), (2,'c')]hoặc một số (gần như) tương đương.

Tất nhiên, enumerate thực sự chỉ là một trình tạo ưa thích:

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

2
Cảm ơn vì lời giải thích này. Tôi đã có một chút khó khăn để tìm ra câu trả lời được chấp nhận. Ít nhất là cho đến khi tôi nhìn thấy của bạn.
trendsetter37

13

Vì bạn có thể gọi hàm này mà không thoát khỏi ngoại lệ bộ nhớ, nó mặc nhiên là lười biếng

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

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

0

Thay thế trường học cũ vì tôi đang sử dụng một máy phát điện mà một người khác (sklearn) đã viết rằng không hoạt động với các phương pháp ở đây.

i=(-1)
for x in some_generator:
    i+=1
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.