【问题标题】:Making a Doubly Linked list iterable使双向链表可迭代
【发布时间】:2016-01-22 11:13:32
【问题描述】:

我不知道在使用嵌套循环时如何使双向链表的可迭代性正常工作。

到目前为止我的代码:http://pastebin.com/PU9iFggr

我试图让它可迭代:

def __iter__(self):
    self.index = 0
    return (self)

def next(self):
    try:
        result = self._findNode(self.index).get()
    except IndexError:
        self.index = 0
        raise StopIteration
    self.index += 1
    return result

def __getitem__(self, item):
    return self._findNode(item).get()

如果在一个 for 循环内,它似乎可以工作,但不能在两个内:

myList = DoublyLinkedList()

myList.append(0)
myList.append(1)
myList.append(2)
myList.append(3)

for i in myList:
    print i         #works as expected

for i in myList:
    for j in myList:
        print j     #goes forever

我想问题是对象内部只有一个 self.index 正在被两个 for 循环更新,但我不知道如何解决这个问题。

【问题讨论】:

  • 因为您迭代同一个实例并使用单个实例属性来跟踪您的迭代。

标签: python class iterable


【解决方案1】:

Containers 应该是 Iterable,而不是 Iterators。不要在类本身上实现next。要么让__iter__ 成为一个生成器函数,要么为它编写一个单独的类来返回,它包装了链表并实现了next

最简单的方法是将__iter__ 定义为generator function

def __iter__(self):
    cur = self.head
    while cur is not None:
        yield cur.value
        cur = cur.nextNode

DoubleLinkedList 中删除next 函数,就是这样。当您尝试使用for 循环对其进行迭代时,对生成器函数的调用将返回一个新的、独立的生成器对象,然后该对象将独立于可能已请求的任何其他生成器进行迭代。而且它比像你做的那样重复索引要快得多(它必须从head开始并每次遍历;生成器会随时保存状态,所以它只遍历链中每个项目的一个链接yielded )。

【讨论】:

    【解决方案2】:

    我想你很清楚问题出在哪里:

    1 for i in mylist: 
    2    for j in mylist:
    3        print j
    4    # when j loop ends index goes back 0, this is where the infinite
    5    # loop is,next line in execution is 1, and the method called is
    6    # "next()", it will read linkedlist[0] for the second time (and
    7    # then repeat...forever)
    

    总之每次你在i循环中调用next,它只会返回doubleLinkedList[0],它会朝着索引异常前进。

    有很多解决方案,
    1.如果你在嵌套for循环中所做的只是print j,你可以简单地遍历你的链表的长度:

    for i in range(len(mylist)): # I see that you already have the __len__ method
        for j in mylist:
            print j
    

    2.这是我最喜欢的解决方案:代替 pf 实现迭代器接口,使用 python 生成器

    def traverseList(doubly_linked_list):
    # select and delete all of your __iter__() and next(), use the following code
        index = 0
        while True:
            try:
                yield doubly_linked_list._findNode(index).get()
                index += 1
            except IndexError:
                break
    
    for i in traverseList(mylist):
         for j in traverseList(mylist):
             # do things, note that I did not create two linked list
             # I sort of create two iterators...
    

    如果你对generators不太熟悉,你可以查一下coroutine,但基本上它们都有自己的栈,所以你的双向链表的每个迭代器都维护着自己的index(您尝试在代码中实现的目标)

    3.hmmm我还在想,如果有新想法我会更新

    【讨论】:

      猜你喜欢
      • 2013-10-10
      • 2015-07-14
      • 2020-07-13
      • 2015-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多