2013-11-01 71 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。 –