2015-09-13 44 views
2

我想創建一個類似列表的類。挑戰在於不使用列表或字典。到目前爲止,我已經創建了一個節點類是這樣的:如何讓MyList可迭代?

class Node: 

    def __init__(self, value=None): 
     self.next = None 
     self.last = None 
     self.value = valor 

    def __repr__(self): 
     return self.value 

而且MyList類,基本上節點鏈,用頭節點和尾節點。事情是,我想讓它迭代,以便我可以運行它。我搜索如何ITER和明年工作,並與這樣的事情上來:

class MyList: 

    def __init__(self): 
     self.head = None 
     self.tail = None 

    def __iter__(self): 
     return self 

    def __next__(self): 
     if self.head: 
      if self.head.next: 
       self.head = self.head.next 
       return self.head.last 
      aux = self.head 
      self.head = None 
      return aux 
     raise StopIteration 

它的工作原理,但它顯然刪除裏面MyList的數據,所以我不能再使用它。任何有關如何獲得相同結果而不搞亂對象內部信息的建議?

+0

你不會產生什麼? –

+0

@RasmusDamgaardNielsen:'__next__'應該返回值,而不是產生它。 – BrenBarn

+0

沒有。我真的不明白髮電機是如何工作的。我已經嘗試了幾次,並以循環結束。 –

回答

6

請注意,迭代器協議只需要the container's __iter__返回一個迭代器;還可以實現__iter__作爲發電機,而不是返回該實例本身:

def __iter__(self): 
    node = self.head 
    while node is not None: 
     yield node 
     node = node.next 
+0

最後,有人使用'__iter__'作爲生成器函數,定義一個新類是如此的矯枉過正。 –

+0

非常感謝@jonrsharpe!其他答案也很有幫助,但這是最簡單的一個:) –

1

您需要爲您的課程添加一個「當前」標記,以通過迭代指示當前指向的節點。事情是這樣的:

class MyList: 

    def __init__(self): 
     self.head = None 
     self.tail = None 
     self.current = self.head 

    def __iter__(self): 
     return self 

    def __next__(self): 
     if self.current is not None: 
      it = self.current 
      self.current = self.current.next 
      return it 
     raise StopIteration 

現在,您的列表不會它的頭和其當前迭代位置區分,但是這是兩個完全不同的概念。

當然,如果你做這種方式,在同一MYLIST所有迭代將「鏈接」,所以,如果你這樣做:

x = MyList(1, 2, 3, 4) 
for item in x: 
    print(x) 
    if item == 2: 
     break 

for item in x: 
    print(x) 

然後第二次迭代將拿起其中先離開。如果你不想要這種行爲,你將不得不創建一個單獨的迭代器類,並且MyList.__iter__返回一個實例,而不是self。如果從__iter__返回self,則該對象不能有多個獨立的迭代進行,因爲迭代狀態作爲迭代的數據存儲在對象中。