链接列表元素上的Python迭代器

时间:2013-11-01 05:29:33

标签: python iterator

如果这个问题错位或重复,我会提前道歉。

此问题在性质上与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对象中的.next参数从一个LinkedAccount迭代到下一个LinkedAccount。

这种方法似乎有效,但是python迭代器文档似乎假设迭代器将遍历父对象包含的元素。是否有任何陷阱妨碍我做这样的事情?

谢谢!

2 个答案:

答案 0 :(得分:4)

听起来它会起作用但是你提到的确切原因在语义上很奇怪。在__iter__上定义LinkedAccount后,听起来就像是在迭代帐户本身而不是帐户列表。你现在拥有的东西让你觉得你正在设置这样的代码行:

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):

答案 1 :(得分:2)

这样做是没有问题的。

将每个LinkedAccount视为集合中的节点,同时也将其视为集合本身,其中包含其后的节点。

链接列表可以被视为节点,也可能被视为另一个链接列表。

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

实际上,这是像Lisp这样的语言中的列表概念。

在功能上或文档方面没有任何东西阻止迭代器返回与调用它的对象相同的类型。同样地,没有禁止集合“包含”(或等效地指向)其他集合,嵌套n-deep。

如果您可以按照上面的列表查看LinkedAccount,这对使用您的代码的人来说很有意义,那么您可能还可以。