【问题标题】:How can I make MyList iterable?如何使 MyList 可迭代?
【发布时间】:2015-12-09 18:45:27
【问题描述】:

我想创建一个行为类似于列表的类。挑战是在不使用列表或字典的情况下做到这一点。到目前为止,我已经创建了一个如下所示的节点类:

class Node:

    def __init__(self, value=None):
        self.next = None
        self.last = None
        self.value = valor

    def __repr__(self):
        return self.value

MyList 类基本上是一个节点链,有一个头节点和一个尾节点。事情是,我想让它可迭代,这样我就可以用它运行一个 for 。我搜索了 iter 和 next 的工作原理并想出了这样的东西:

class MyList:

    def __init__(self):
        self.head = None
        self.tail = None

    def __iter__(self):
        return self

    def __next__(self):
        if self.head:
            if self.head.next:
                self.head = self.head.next
                return self.head.last
            aux = self.head
            self.head = None
            return aux
        raise StopIteration

它有效,但它显然删除了MyList 中的数据,所以我不能再次使用它。关于如何在不弄乱对象内部信息的情况下获得相同结果的任何建议?

【问题讨论】:

  • 你什么都没产出?
  • @RasmusDamgaardNielsen: __next__ 应该返回值,而不是屈服。
  • 不。老实说,我不明白生成器是如何工作的。我已经尝试了几次并以循环结束。
  • @dm295 in python3 语法改为next

标签: python list class functional-programming nodes


【解决方案1】:

您需要在您的类中添加一个“当前”标记,以指示迭代当前指向的节点。像这样的:

class MyList:

    def __init__(self):
        self.head = None
        self.tail = None
        self.current = self.head

    def __iter__(self):
        return self

    def __next__(self):
        if self.current is not None:
            it = self.current
            self.current = self.current.next
            return it
        raise StopIteration

目前,您的列表不区分其头部和当前迭代位置,但这是两个完全不同的概念。

当然,如果你这样做,同一个 MyList 上的所有迭代都将被“链接”,所以如果你这样做:

x = MyList(1, 2, 3, 4)
for item in x:
    print(x)
    if item == 2:
        break

for item in x:
    print(x)

然后第二次迭代将从第一次停止的地方开始。如果您不想要这种行为,则必须创建一个单独的迭代器类,并让MyList.__iter__ 返回它的一个实例,而不是self。如果您从__iter__ 返回self,则该对象不能进行多次独立迭代,因为迭代状态作为被迭代的数据存储在对象中。

【讨论】:

    【解决方案2】:

    注意迭代器协议只要求the container's __iter__返回一个迭代器;您还可以将__iter__ 实现为生成器,而不是返回实例本身:

    def __iter__(self):
        node = self.head
        while node is not None:
            yield node
            node = node.next
    

    【讨论】:

    • 终于有人用__iter__作为生成器函数了,定义一个新类实在是太过分了。
    • 非常感谢@jonrsharpe!其他答案也很有帮助,但这是最简单的一个:)
    猜你喜欢
    • 2012-03-16
    • 2011-01-08
    • 2017-12-25
    • 2018-08-06
    • 2011-01-08
    • 2021-11-14
    • 2020-09-07
    • 2019-09-14
    相关资源
    最近更新 更多