5

如果这个问题放错地方或重复,我提前道歉。

这个问题本质上类似于双重链接列表迭代器 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 迭代到下一个。

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

谢谢!

4

2 回答 2

5

听起来它会起作用,但由于您提到的确切原因,它在语义上很奇怪。__iter__定义 on听起来像是在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):
于 2013-11-01T05:41:06.960 回答
3

这样做没有问题。

不仅可以将每个LinkedAccount节点视为集合中的一个节点,还可以将其视为集合本身,其中包括它之后的节点。

链表可以被认为是一个节点,也可能是另一个链表。

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

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

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

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

于 2013-11-01T05:42:12.560 回答