为了账号安全,请及时绑定邮箱和手机立即绑定

在 Python 链表中使用 __iter__ 和 __next__ 时出错?

在 Python 链表中使用 __iter__ 和 __next__ 时出错?

明月笑刀无情 2023-10-06 18:45:46
def __iter__(self):    return selfdef __next(self):    if self.head is None:        raise StopIteration    else:        return self.head.next基本上,我根据 W3 学校的基本示例尝试了这些方法的实现。它不喜欢iter返回 LinkedList 的对象类型。错误:TypeError:iter() 返回类型为“LinkedList”链表的非迭代器如果我尝试返回 self.head,它不喜欢它是一个节点对象?错误:TypeError:iter() 返回“Node”类型的非迭代器我正在尝试使用 forloop 使我的 LinkedList 可迭代,但我遇到了困难。有谁知道在Python中使LinkedList可迭代的正确实现吗?这里的类似问题对我来说没有意义,并且解决方案不适合我的使用。
查看完整描述

1 回答

?
开心每一天1111

TA贡献1836条经验 获得超13个赞

下一项的 dunder 方法不是__next__,__next并且您似乎缺少在迭代时实际在列表中移动的代码。


我使用的常规方法是在类型中使用一个单独的迭代器类来完成繁重的工作。此外,设置列表的方式也使得元素类的想法变得可取(如果您使用Python列表,则不需要这样做,但是,由于您需要一个and“指针”,所以最好将其作为单独的item列表next)班级)。


让我们首先创建带有封闭项目类的列表类:


class MyList:

    # Single element in the list.


    class MyListElem:

        def __init__(self, item, link_from = None, link_to = None):

            # Set data, link from previous and to next if specified.


            self._item = item

            self._next = link_to

            if link_from is not None:

                link_from.change_link(self)


        def change_link(self, item):

            self._next = item

元素类有两种方法,第一种方法根据需要创建带有链接的元素。目前(见MyList.add()下文),to链接始终是None因为我们仅附加到列表中。


类似地,from链接要么是None当前尾部,要么是当前尾部,具体取决于我们是将第一个元素还是后续元素添加到列表中。


这些参数主要是为了满足以后能够插入列表中任意位置的可能性。


接下来是迭代器类,也是列表类的一部分:


    # Iterator over the list.


    class MyListIter:

        def __init__(self, head):

            # Start at the head.


            self._curr = head


        def __iter__(self):

            # To iterate over the iterator rather than collection.


            return self


        def __next__(self):

            # Check more left, advance to next and return current.


            if self._curr is None:

                raise StopIteration

            ret_val = self._curr._item

            self._curr = self._curr._next

            return ret_val

这相对简单,初始化器只是设置我们以便第一次调用将返回头部。该__iter__调用允许您从集合中检索迭代器,然后对其进行迭代,而不是直接在集合上进行迭代。区别在于:


for iter in object:         # iterate over object

    pass

iter = object.__iter__()    # iterate over iterator

for iter2 in iter:

    pass

有关为什么需要这样做的更多详细信息,请参阅此处。

调用__next__是迭代器的“核心”。如果迭代器完成,它会引发异常。否则,它会在前进到下一个值后返回当前值。


然后是列表类本身,一个非常简单的类,只允许追加到末尾,不允许删除,并且有一个迭代器来处理它:


    # The list itself.


    def __init__(self):

        # Empty list to start with.


        self._head = None

        self._tail = None


    def add(self, val):

        # Append to the end of the list.


        if self._head is None:

            self._head = self.MyListElem(val)

            self._tail = self._head

        else:

            self._tail = self.MyListElem(val, self._tail)


    def __iter__(self):

        return self.MyListIter(self._head)

这真的很容易(嗯,相对容易)。以下测试代码显示了它的实际效果:


x = MyList()

x.add(12345)

x.add(42)

x.add("Hello")

x.add([1, 2, 3])

for i in x:

    print(i)

正如预期的那样,其输出是:


12345

42

Hello

[1, 2, 3]


查看完整回答
反对 回复 2023-10-06
  • 1 回答
  • 0 关注
  • 50 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信