2009-10-22 40 views
16

Mặc dù đọc lên trên nó, tôi vẫn không hoàn toàn hiểu làm thế nào __iter__ hoạt động. Điều gì sẽ là một giải thích đơn giản?__iter__ hoạt động như thế nào?

Tôi đã xem def__iter__(self): return self. Tôi không thấy cách làm việc này hoặc các bước về cách thức hoạt động của nó.

+3

Những chương trong đó cuốn sách? Điều đó sẽ giúp chúng tôi thu hẹp nguồn gốc của sự nhầm lẫn của bạn. –

+0

học python chương 24 trang 493 - 495 – sss

+0

Nếu bạn nhìn vào mô-đun itertools tài liệu thư viện chuẩn, bạn sẽ tìm thấy một số hàm yêu cầu phương thức __iter __() để hoạt động. –

Trả lời

6

Trình lặp cần xác định hai phương pháp: __iter__()__next__() (next() trong python2). Thông thường, đối tượng tự xác định phương thức __next__() hoặc next(), do đó, nó chỉ trả về chính nó làm trình lặp. Điều này tạo ra một có thể lặp lại cũng là một trình biến đổi . Các phương pháp này được sử dụng bởi các câu lệnh forin.

Python 3 tài liệu: docs.python.org/3/library/stdtypes.html#iterator-types

Python 2 tài liệu: docs.python.org/2/library/stdtypes.html#iterator-types

+4

Trở thành '__next __()' thay vì 'next()' trong Python 3. – JeromeJ

+3

Điều này gây nhầm lẫn. Đặc biệt là vì bạn nói điều gì đó, sau đó ngay lập tức nói đó là một lời nói dối. Lol, chỉ cần cập nhật nó là chính xác –

2

Một lớp học hỗ trợ phương thức __iter__ sẽ trả về một thể hiện đối tượng trình lặp: một đối tượng hỗ trợ phương thức tiếp theo(). Đối tượng này sẽ có giá trị trong các câu lệnh "for" và "in".

21

Như đơn giản như tôi có thể đặt nó:

__iter__ định nghĩa một phương pháp trên một lớp mà sẽ trả về một iterator (một đối tượng mà liên tiếp mang lại các mục tiếp theo chứa bởi đối tượng của bạn).

Đối tượng trình lặp mà __iter__() trả về có thể là bất kỳ đối tượng nào, miễn là nó xác định phương thức next().

Phương thức next sẽ được gọi bằng các câu lệnh như for ... in ... để mang lại mục tiếp theo và next() sẽ tăng ngoại lệ StopIteration khi không có thêm mục nào.

Có gì tuyệt vời về việc này là nó cho phép bạn xác định cách đối tượng của bạn được lặp, và __iter__ cung cấp một giao diện phổ biến mà mọi chức năng python khác biết làm thế nào để làm việc với.

2

Trong Python, một trình lặp là bất kỳ đối tượng nào hỗ trợ giao thức trình lặp. Một phần của giao thức đó là đối tượng phải có phương thức __iter__() trả về đối tượng trình lặp. Tôi cho rằng điều này mang lại cho bạn một số tính linh hoạt để một đối tượng có thể chuyển giao trách nhiệm của vòng lặp cho một lớp bên trong hoặc tạo một số đối tượng đặc biệt. Trong mọi trường hợp, phương pháp __iter__() thường chỉ có một dòng và đường đó thường chỉ đơn giản là return self

Phần khác của giao thức là phương pháp next() và đây là nơi thực hiện công việc thực. Phương pháp này phải tìm ra hoặc tạo ra hoặc nhận được điều tiếp theo, và trả lại nó. Nó có thể cần phải theo dõi nó ở đâu để lần sau nó được gọi, nó thực sự trả lại điều tiếp theo.

Một khi bạn có một đối tượng trả về điều tiếp theo trong một chuỗi, bạn có thể thu gọn vòng lặp for trông như thế này:

myname = "Fredericus" 
x = [] 
for i in [1,2,3,4,5,6,7,8,9,10]: 
    x.append(myname[i-1]) 
    i = i + 1 # get the next i 
print x 

vào đây:

myname = "Fredericus" 
x = [myname[i] for i in range(10)] 
print x 

Chú ý rằng có không có nơi nào chúng ta có mã nhận giá trị tiếp theo của i vì phạm vi (10) là một đối tượng theo sau giao thức vòng lặp, và việc hiểu danh sách là một cấu trúc sử dụng giao thức vòng lặp.

Bạn cũng có thể sử dụng giao thức trình lặp trực tiếp. Ví dụ, khi viết kịch bản để xử lý các file CSV, tôi thường viết này:

mydata = csv.reader(open('stuff.csv') 
mydata.next() 
for row in mydata: 
    # do something with the row. 

Tôi đang sử dụng iterator trực tiếp bằng cách gọi next() bỏ qua dòng tiêu đề, sau đó sử dụng nó một cách gián tiếp thông qua in nhà điều hành được xây dựng trong trong for tuyên bố.

5

Thông số kỹ thuật cho def __iter__(self): là: nó trả về một trình lặp. Vì vậy, nếu self là một trình lặp, thì return self rõ ràng là phù hợp.

"Là trình lặp" có nghĩa là "có phương thức __next__(self)" (bằng Python 3; trong Python 2, tên của phương thức được đề cập không may là next thay vào đó, rõ ràng là thiết kế tên trục trặc cho phương pháp đặc biệt). Trong Python 2.6 và cao hơn, cách tốt nhất để thực hiện một iterator nói chung là sử dụng lớp cơ sở trừu tượng thích hợp từ collections thư viện chuẩn module - trong Python 2.6, mã có thể (nhớ gọi phương thức __next__ để thay thế bằng Python 3):

import collections 

class infinite23s(collections.Iterator): 
    def next(self): return 23 

một thể hiện của lớp này sẽ trở lại vô cùng nhiều bản sao của 23 khi lặp trên (như itertools.repeat(23)) để vòng lặp phải được chấm dứt bằng cách khác. Vấn đề là phân lớp collections.Iterator bổ sung phương thức __iter__ đúng vào danh nghĩa của bạn - không phải là một vấn đề lớn ở đây, nhưng là nguyên tắc chung tốt (tránh lặp lại, mã soạn sẵn như tiêu chuẩn của trình vòng lặp __iter__ - trong sự lặp lại, không có giá trị gia tăng và rất nhiều giá trị trừ! -).

+0

Trong đoạn 2, định dạng SO đã thay đổi '__next__' thành chữ đậm 'next'. Đáng giá để sửa chữa. –

+0

@Craig, nhưng nó được cho là 'next' không' __next__' –

+0

Trong Python 2, nó là 'next', nhưng trong Python 3 nó đã được đổi tên thành' __next__', như Alex đang định nói. –

Các vấn đề liên quan