2016-11-05 87 views
2

爲什麼一個課程需要定義__iter__()返回自我,以獲得該類的迭代器?爲什麼一個類需要__iter __()來返回一個迭代器?

class MyClass: 
    def __init__(self): 
     self.state = 0 

    def __next__(self): 
     self.state += 1 
     if self.state > 4: 
      raise StopIteration 
     return self.state 

myObj = MyClass() 
for i in myObj: 
    print(i) 

控制檯日誌:

Traceback (most recent call last): 
    for i in myObj: 
TypeError: 'MyClass' object is not iterable 

答案https://stackoverflow.com/a/9884259/4515198

迭代器是與下一個(Python的2)或__next__(Python 3中)的方法的對象。

加入以下的任務:

def __iter__(self): 
    return self 

是返回一個迭代,或者類,它定義了__next__()方法的對象。

但是,當MyClass在myObj = MyClass()行中實例化時,不是返回已由__new__()方法完成的MyClass對象的任務(它定義了__next__()方法)?

不會定義__next__()方法的類的對象是自己的迭代器嗎?

我已經研究了問題What is the use of returning self in the __iter__ method?Build a Basic Python Iterator,但我仍然無法理解讓方法返回自我的原因。

回答

2

不說,已經由__new__()方法

都能跟得上完成,__new__僅僅是另一種方法,它不會自動爲對象創建__iter__

不會定義__next__()方法的類的對象是自己的迭代器嗎?

不一定,因爲您的第一堂課定義爲__next__但不是__iter__顯示。 __next__需要如果您需要支持迭代,因爲它會生成值。 __iter__是需要的,因爲這就是for語句中的一個對象所要求的,以便它獲得一個迭代器。

你可以有一個類,只定義__next__和有些作品(它是有限的),但它需要從某人__iter__返回。例如,類MyClass返回類CustomIter只定義__next__

class MyClass: 
    def __iter__(self): 
     return CustomIter() 

class CustomIter(object): 

    def __init__(self): 
     self.state = 0 

    def __next__(self): 
     self.state += 1 
     if self.state > 4: 
      raise StopIteration 
     return self.state 

你需要一個對象,將返回另一個對象上定義一個__iter__(可能是本身)上__next__定義。


如果你的類定義__iter__爲:

def __iter__(self): return self 

,那麼你需要在type(self)(類)定義__next__因爲你返回的實例本身。 __next__將會在self上被調用,直到不能產生更多的值。

另一種情況是當__iter__只是返回另一個定義爲__next__的對象(按照我的第一個示例)。您也可以通過製作__iter__生成器來做到這一點。

例如:

class MyClass: 
    def __init__(self): 
     self.state = 0 

    def __iter__(self): 
     for i in range(10): yield i 

沒有定義__next__。當iter被調用它,但:

g = iter(MyClass()) 

它返回一個發電機g定義__next__

g = iter(MyClass()) 

g.__next__() # 0 
g.__next__() # 1 
+0

我的意思是在「__new __()'方法中已經做過的事情」是,當已經創建了__new __() MyClass的一個對象,爲什麼我們需要通過'__iter __()'來再次返回MyClass對象? –

+0

當我得到它時,像'for' ** _必須_ **這樣的循環調用'__iter __()'方法來獲取MyClass的實例或任何類的實例。這是它在python中的工作方式嗎? –

+0

如果存在,@ thebeliever3。您在問題主體中的鏈接中提供了回退選項(例如,如果沒有找到__iter__,則嘗試'__getitem__'。) –

6

答案的問題爲什麼__iter __()方法是必要的是對於for-loops總是通過調用iter()對象得到一個迭代器。這就是爲什麼即使是迭代器也需要使用for循環來處理迭代器。在調用iter(),然後在結果迭代器上調用__next __()來獲得一個值。

用於創建iterables和迭代器的規則是:

1)Iterables具有__iter __()方法,該方法返回迭代器。

2)迭代器具有__next __()方法返回一個值,該更新的狀態中,並且提出了StopIteration異常時完成。

3)迭代器本身有一個__iter __()方法返回自我。這意味着所有迭代器都是可自我迭代的。

的最後一條規則的用於具有__iter __()方法返回自我迭代器好處是,它可以讓我們以繞過部分消耗的迭代器

>>> s = 'hello world' 
>>> it = iter(s) 
>>> next(it) 
'h' 
>>> next(it) 
'e' 
>>> list(it)  # Doesn't start from the beginning 
['l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'] 

這裏的另一個例子取決於迭代器在不重新啓動的情況下自迭代:

>>> s = 'hello world' 
>>> it = iter(s) 
>>> list(zip(it, it)) 
[('h', 'e'), ('l', 'l'), ('o', ' '), ('w', 'o'), ('r', 'l')] 

注:

1)的另一種方法,使一個可迭代是提供一種__getitem __()方法接受連續指數和引發IndexError時完成。這是如何在Python 2中迭代對象的str

2)像文件這樣的對象是它們自己的迭代器。這意味着您可以直接在文件對象上調用next()。這也意味着文件不能有多個獨立的迭代器(文件對象本身具有跟蹤文件中的位置的狀態)。

3)上述迭代器設計模式不是Python特定的。這是一個用於許多OOP語言的通用設計模式:https://en.wikipedia.org/wiki/Iterator_pattern

相關問題