2013-05-29 35 views
104

xem xét:danh sách Python iterator hành vi và tiếp theo (iterator)

>>> lst = iter([1,2,3]) 
>>> next(lst) 
1 
>>> next(lst) 
2 

Vì vậy, thúc đẩy iterator được, như mong đợi, xử lý bởi đột biến cùng đối tượng.

Đây là trường hợp, tôi sẽ mong đợi:

a = iter(list(range(10))) 
for i in a: 
    print(i) 
    next(a) 

để bỏ qua mọi yếu tố thứ hai: cuộc gọi đến next nên thúc đẩy các iterator một lần, sau đó cuộc gọi ngầm thực hiện bởi các vòng lặp nên đẩy nó một lần thứ hai - và kết quả của cuộc gọi thứ hai này sẽ được gán cho i.

Không. Vòng lặp in tất cả của các mục trong danh sách, mà không bỏ qua bất kỳ mục nào. Suy nghĩ đầu tiên của tôi là điều này có thể xảy ra bởi vì vòng lặp gọi iter trên những gì nó được thông qua, và điều này có thể cung cấp cho một iterator độc lập - đây không phải là trường hợp, vì chúng tôi có iter(a) is a.

Vì vậy, tại sao next không xuất hiện để nâng cao trình lặp trong trường hợp này?

Trả lời

137

Những gì bạn thấy là dịch lặp lại giá trị trả về của next() ngoài i được in mỗi lần lặp:

>>> a = iter(list(range(10))) 
>>> for i in a: 
... print(i) 
... next(a) 
... 
0 
1 
2 
3 
4 
5 
6 
7 
8 
9 

Vì vậy 0 là sản phẩm của print(i), 1 sự trở lại giá trị từ next(), được lặp lại bởi trình thông dịch tương tác, v.v .. Chỉ có 5 lần lặp, mỗi lần lặp lại dẫn đến 2 dòng được ghi vào thiết bị đầu cuối.

Nếu bạn gán đầu ra của next() mọi thứ làm việc như mong đợi:

>>> a = iter(list(range(10))) 
>>> for i in a: 
... print(i) 
... _ = next(a) 
... 
0 
2 
4 
6 
8 

hoặc in thêm thông tin để phân biệt print() đầu ra từ người phiên dịch tiếng vang tương tác:

>>> a = iter(list(range(10))) 
>>> for i in a: 
... print('Printing: {}'.format(i)) 
... next(a) 
... 
Printing: 0 
1 
Printing: 2 
3 
Printing: 4 
5 
Printing: 6 
7 
Printing: 8 
9 

Nói cách khác , next() hoạt động như mong đợi, nhưng vì nó trả về giá trị tiếp theo từ trình lặp, được lặp lại bởi trình thông dịch tương tác, bạn được dẫn đến tin rằng vòng lặp có bản sao lặp của riêng nó bằng cách nào đó.

+8

Tôi không nhận thức được hành vi này từ trình thông dịch. Tôi vui vì tôi đã phát hiện ra rằng trước khi mất rất nhiều thời gian để tự hỏi về nó trong khi giải quyết một số vấn đề thực sự. – brandizzi

+3

... \ * chết *. Điều tồi tệ nhất là tôi có thể nhớ chính xác hành vi thông dịch này cho một người có lẽ cách đây một tuần. – lvc

+0

thú vị. Tôi đã cố gắng cho tôi trong một: tiếp theo (a); in tôi và nghĩ rằng tôi sẽ nhảy đến 1 và in 1,3,5,7,9. Nhưng nó vẫn là 0,2,4,6,8. Tại sao? – user2290820

2

Đã xảy ra lỗi với Python/Máy tính của bạn.

a = iter(list(range(10))) 
for i in a: 
    print(i) 
    next(a) 

>>> 
0 
2 
4 
6 
8 

Làm việc như mong đợi.

Được thử nghiệm bằng Python 2.7 và bằng Python 3+. Hoạt động đúng trong cả hai

+5

tôi nhận được kết quả tương tự như @lvc (chỉ trên IDLE tuy nhiên, khi thực hiện như kịch bản tôi có được điều này)) – jamylak

+3

@Inbar Rose Chỉ khi bạn chạy dưới dạng tập lệnh. – thecoder16

+0

nó là hành vi đưa mã thông qua trình bao tương tác. Nếu hàm trả về giá trị mà không được sử dụng, trình thông dịch sẽ in nó thành trình bao dưới dạng đầu ra gỡ lỗi – Reishin

10

Điều đang xảy ra là next(a) trả về giá trị tiếp theo của a, được in vào bảng điều khiển vì nó không bị ảnh hưởng.

Những gì bạn có thể làm là ảnh hưởng đến một biến với giá trị này:

>>> a = iter(list(range(10))) 
>>> for i in a: 
... print(i) 
... b=next(a) 
... 
0 
2 
4 
6 
8 
6

tôi tìm ra câu trả lời hiện có một chút bối rối, bởi vì họ chỉ gián tiếp chỉ ra điều bí ẩn cần thiết trong ví dụ mã: cả * "print i" và "next (a)" đang khiến kết quả của chúng được in ra.

Vì chúng đang in các phần tử xen kẽ của chuỗi gốc và không có gì xảy ra khi câu lệnh "tiếp theo (a)" xuất hiện, như thể câu lệnh "print i" đang in tất cả các giá trị. Trong ánh sáng đó, nó trở nên rõ ràng hơn rằng gán kết quả của "tiếp theo (a)" cho một biến ức chế việc in kết quả của nó, để chỉ các giá trị thay thế mà biến vòng lặp "i" được in. Tương tự như vậy, làm cho các "in" tuyên bố phát ra một cái gì đó đặc biệt hơn nữa disambiguates nó, là tốt.

(Một trong các câu trả lời hiện bác bỏ những người khác vì câu trả lời đó là có mã ví dụ đánh giá là một khối, do đó người phiên dịch không báo cáo các giá trị trung gian cho "bên cạnh (a)".)

Các điều beguiling trong trả lời câu hỏi, nói chung, là được rõ ràng về những gì là hiển nhiên khi bạn biết câu trả lời. Nó có thể khó hiểu. Tương tự như vậy critiquing câu trả lời một khi bạn hiểu chúng. Thật thú vị ...

1

Nó hoạt động theo cách bạn muốn nếu gọi là một hàm:

>>> def test(): 
...  a = iter(list(range(10))) 
...  for i in a: 
...   print(i) 
...   next(a) 
... 
>>> test() 
0 
2 
4 
6 
8