2013-11-01 70 views
4

如果這個問題錯位或重複,我很抱歉提前。鏈表元素上的Python迭代器

此問題在性質上與doubly Linked list iterator python相似。然而,與引用的問題不同,我不想創建一個包含大量元數據並提供迭代器(它們不是我的應用程序所必需的)的首要鏈接列表對象。

我的問題是:有沒有什麼根本的原因,我不應該或不能提供一個迭代器,它不會迭代它包含的元素,而是跳過通過引用鏈接到彼此的不同元素對象?

迭代器不是代碼正常運行所必需的,但我更喜歡for item in構造的語法糖。

我的實現看起來有點像這樣(簡體版):

class LinkedAccount: 
    def __init__(self, someParameter, nextAccount = None, prevAccount = None): 

     self.someParameter = someParameter 

     self.next = nextAccount 
     self.prev = prevAccount 
     if nextAccount is not None: 
      self._tell_next() 
     if prevAccount is not None: 
      self._tell_prev() 

    def _tell_next(self): 
     if self.next is not None: 
      self.next._recv_next(self) 

    def _recv_next(self,prevAccount): 
     self.prev = prevAccount 

    def _tell_prev(self): 
     if self.prev is not None: 
      self.prev._recv_prev(self) 

    def _recv_prev(self,nextAccount): 
     self.next = nextAccount 


    def __iter__(self): 
     return AccountIterator(self) 

class AccountIterator: 
    def __init__(self,Account): 
     self.Account = Account 

    def __iter__(self): 
     return self 

    def next(self): 
     if self.Account is None: 
      raise StopIteration 
     else: 
      curAccount = self.Account 
      self.Account = self.Account.next 
      return curAccount 

的LINKEDACCOUNT對象提供迭代從一個LINKEDACCOUNT到下使用。接下來的參數已經存儲在LINKEDACCOUNT對象的迭代器。

這種方法似乎可行,但python迭代器文檔似乎假設迭代器將遍歷父對象包含的元素。是否有任何缺陷阻止我做這樣的事情?

謝謝!

回答

2

沒有與做這種方式沒有問題。

將每個LinkedAccount看作不僅是一個集合中的一個節點,也是一個集合本身,其中包括它後面的節點。

鏈接列表可能被認爲是一個節點,也可能是另一個鏈接列表。

[1, [2, [3, [4]]]] 

確實,這是Lisp這樣的語言列表的概念。

沒有什麼,在功能上或文檔方面,排除迭代器返回與它所調用的對象相同的類型。同樣,對於「包含」(或等價地指向)其他集合,嵌套n深的集合也沒有禁止。

如果您可以查看您的LinkedAccount(如上面的列表),並且這對於使用您的代碼的人員來說是有意義的,那麼您可能沒問題。

+0

我理解這個問題的方式是,這不是一個集合列表,但是他有一個集合中的項目會返回迭代集合的迭代器。所以用Lisp來說,就像試圖讓它編寫代碼,它在語義上意味着迭代列表的「car」,但實際上遍歷列表本身。 –

+0

非常感謝您對這個問題所做的書面和直接的回答:這種實施可能存在的技術問題! –

+0

@ChadMiller,'car'沒有指向下一個項目的指針,但LinkedAccount' *確實有一個指向下一個項目的指針。因此,在這個類比中'LinkedAccount'是'cons','LinkedAccount.someParemeter'是'car'。 –

2

這聽起來像它會起作用,但它在語義上很奇怪,因爲你提到的確切原因。在LinkedAccount上定義__iter__使其聽起來像您正在迭代帳戶本身而不是帳戶列表。你現在擁有的東西看起來像是你設置了這樣的代碼行:

for list_item in head_of_list: 

這是沒有意義的。在這種情況下,我覺得你可以只def一個簡單的發電機:

def iterate_from(list_item): 
    while list_item is not None: 
     yield list_item 
     list_item = list_item.next 

,它允許你這樣寫代碼:

for list_item in iterate_from(head_of_list): 
+0

感謝您的文體建議!我真的有很長的路要走,寫下真正的'pythonic'代碼 - 我的大部分代碼在過去幾年都是Perl。 –