Python链表元素的迭代器

5

如果这个问题放错了地方或是重复提问,我先向大家致歉。

这个问题的性质类似于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个回答

5
听起来好像会有用,但正如你提到的原因,它在语义上有些奇怪。如果在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):

3

这种做法没有问题。

将每个LinkedAccount视为不仅是集合中的节点,而且还包括它之后的节点的集合本身。

可以将链表视为一个节点以及可能包含另一个链表。

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

事实上,在Lisp等语言中,这就是列表的概念。

从功能或文档方面来看,没有什么能阻止迭代器返回与其调用对象相同的类型。同样,也没有禁止集合“包含”(或等效地指向)其他集合,可以嵌套到n层。

如果您愿意将LinkedAccount视为上述列表,并且对于使用您代码的人来说这是有意义的,那么您可能没问题。


我理解这个问题的方式是,这不是一个集合列表,而是他想让集合中的项返回迭代器来迭代整个集合。所以用Lisp的术语来说,就像尝试编写的代码在语义上意味着迭代列表的car,但实际上是在迭代列表本身。 - Free Monica Cellio
感谢您对于关于此类实现可能存在的技术问题所作出的清晰明了的回答! - Hao Cheng
@ChadMiller,car没有指向下一个项目的指针,但是LinkedAccount 确实有指向下一个项目的指针。因此,在这个类比中,LinkedAccountcons,而LinkedAccount.someParemetercar - Paul Draper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接