【问题标题】:Python - set variable inside __iter__ method [closed]Python - 在 __iter__ 方法中设置变量
【发布时间】:2020-05-15 21:23:52
【问题描述】:

这对我来说似乎是一个错误,我无法真正弄清楚为什么。

我有一个非常简单的自定义 LinkedList 类:

class MyLinkedList:

    def __init__(self):
        self.head = None

    def __iter__(self):
        self.currNode = self.head
        return self

    def __next__(self):
        if self.currNode:
            res = self.currNode
            self.currNode = self.currNode.next
            return res
        else:
            raise StopIteration

    def addAtHead(self, val: int) -> None:
        currNode = self.head

        self.head = Node(val, currNode)

问题来自 iter 方法。在我将 head 节点添加到空的linkedList 后,iter 仍然认为 self.head 为 None!在调试节点中,我可以看到 self.head 是一个有效的 not none 实例,但是在将其值分配给 self.currNode 之后,self.currNode 原来是 None。

我认为这可能是属性问题,所以我将属性更改为属性。但问题仍然存在。我哪里错了?

    @property
    def head(self):
        return self._head

    @head.setter
    def head(self, x):
        self._head = x

添加我的调用堆栈:

    ll = MyLinkedList()
    ll.addAtTail(6)
    ll.addAtHead(5)
    ll[0] # is None 

    #where a __getitem__ is defined as:
    def __getitem__(self, i):
        n = 0
        for node in self:
            if n == i:
                return node
            n += 1
        raise IndexError


class Node:
    def __init__(self, val=None, next=None):
        self.val = val
        self.next = next         

【问题讨论】:

  • 不要让列表成为自己的迭代器。一些教程建议这样做,但这是一个非常糟糕的主意,因为如果您尝试使用嵌套循环或同时或可重入地迭代列表,它会中断。
  • "iter 仍然认为 self.head 是 None!"我不明白;您显示的调试器屏幕截图清楚地显示了head = {Node} ...。无论如何,您能否展示一个尝试使用导致意外错误的类 的示例? IDE 并不总是能正确处理所有事情,或者它们可能会显示不同步的内容。
  • 您需要展示您如何使用它(使用minimal reproducible example)以便我们提供完整的答案,但主要问题可能是您还没有编写迭代器类。迭代器必须具有幂等的 __iter__ 方法(在 99.99% 的情况下,它们应该什么都不做,但 return self),因为 Python 假设它可以在现有的迭代器上愉快地调用 __iter__ 并且什么都不做。如果您希望这是一个 iterable,则不应定义 __next__,并且通常将 __iter__ 编写为生成器函数(将所有逻辑迁移到 __iter__ 并使用 @987654334 @ 其中__next__ 将使用return)。
  • @user1438644:那是另一回事。该节点不应该是一个迭代器。
  • 我无法重现您的问题,但也许我正在做一些与您不同的事情,因为很难说出您到底在运行什么。我使用了第一个块中的 MyLinkedList 类,并在最后一个块中添加了 __getitem__ 方法。我还从您的最后一个块创建了 Node 类。然后最后一个块中的其余代码工作正常。当我执行ll[0] 时,我得到了一个节点。

标签: python


【解决方案1】:
class Node:
    def __init__(self, val=None, nxt=None):
        self.val = val
        self.n = nxt 

class MyLinkedList:

    def __init__(self):
        self.head = None

    def __iter__(self):
        self.currNode = self.head
        return self

    def __next__(self):
        if self.currNode:
            res = self.currNode.val
            self.currNode = self.currNode.n
            return res
        else:
            raise StopIteration

    def addAtHead(self, val: int) -> None:
        currNode = self.head

        self.head = Node(val, currNode)


n = MyLinkedList()
n.addAtHead(4)
n.addAtHead(5)
n.addAtHead(7)

for i in n:
    print(i)

得到

7
5
4

【讨论】:

  • 这就是你认为next 需要成为一种方法的原因吗?您可以通过val 访问该值。你不需要一个方法。 next 旨在成为原始代码中下一个节点的链接。它不应该是一个值访问器。将节点值访问器命名为 next 是一个奇怪的名称选择。
  • 一个没有一句话的答案什么都没有,你可以解释问题是什么,你做了什么来解决它,为什么它会解决它
猜你喜欢
  • 1970-01-01
  • 2019-09-07
  • 1970-01-01
  • 2021-12-29
  • 1970-01-01
  • 2011-02-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-23
相关资源
最近更新 更多