Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python __双链接哨兵列表中的next和iter方法_Python_Python 3.x_Doubly Linked List - Fatal编程技术网

Python __双链接哨兵列表中的next和iter方法

Python __双链接哨兵列表中的next和iter方法,python,python-3.x,doubly-linked-list,Python,Python 3.x,Doubly Linked List,我现在正在研究一个双链表类,我的next和iter方法遇到了麻烦。这是为我的班级准备的一个项目,我已经上交了,现在只想了解如何实际修复它,使它变得有用 我想让我的代码做的是设置一个当前指针,从标题开始,然后继续前进,直到指示终止或到达尾部。我想访问存储在每个节点上的值。节点类是主链表类的子类。这是我的密码。当我调用我的方法(发布我的append方法)时,我的问题出现了;无法识别当前指针。有没有办法解决这个问题 class Linked_List: class __Node:

我现在正在研究一个双链表类,我的next和iter方法遇到了麻烦。这是为我的班级准备的一个项目,我已经上交了,现在只想了解如何实际修复它,使它变得有用

我想让我的代码做的是设置一个当前指针,从标题开始,然后继续前进,直到指示终止或到达尾部。我想访问存储在每个节点上的值。节点类是主链表类的子类。这是我的密码。当我调用我的方法(发布我的append方法)时,我的问题出现了;无法识别当前指针。有没有办法解决这个问题

class Linked_List:

    class __Node:
        def __init__(self, val):
          self.val = val
          self.size = 0

    def __init__(self):
        self.header = Linked_List.__Node('header')
        self.trailer = Linked_List.__Node('trailer')
        self.header.next = self.trailer
        self.trailer.prev = self.header
        self.size = 0
        self.current = self.header
        self.current.next = self.trailer

    def __iter__(self):
        self.current = self.header
        return self


    def __next__(self):
        if self.current == self.trailer:
            raise StopIteration
        result = self.Linked_List.__Node[self.current]
        self.current = self.current.next
        return result

    def append(self, val):
        new_node = Linked_List.__Node(val)

        if self.header.next is self.trailer:
            self.header.next = new_node
            self.trailer.prev = new_node
            self.current = self.header
        else:
            while self.current is not self.trailer:
                self.current = self.current.next
            self.current.next = new_node
            new_node.next = self.trailer
            new_node.prev = self.current
        self.size += 1

我对python(以及一般的编码)比较新,所以任何建议都会令人惊讶。

您的代码有多个问题,当您尝试使用它时,这些问题会变得很明显。让我们假设以下代码来测试它:

l = Linked_List()
l.append('foo')
l.append('bar')
l.append('baz')

print([x.val for x in l])

AttributeError:“\uu节点”对象没有属性“next”

第一个问题:您的
\u节点
类型没有用于
下一个
上一个
的字段:

class __Node:
    def __init__(self, val):
      self.val = val
      self.size = 0
      self.prev = None
      self.next = None
AttributeError:“非类型”对象没有属性“下一个”

第二个问题:
next
并不总是为附加节点填充。在
append
中的一个路径中,不设置新节点的
next
prev

def append(self, val):
    new_node = Linked_List.__Node(val)

    if self.header.next is self.trailer:
        # set the attributes on new_node
        new_node.prev = self.header
        new_node.next = self.trailer

        self.header.next = new_node
        self.trailer.prev = new_node
        self.current = self.header
    # …
AttributeError:“链接列表”对象没有属性“链接列表”

第三个问题:不知道你在
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。您只需在那里访问
self.current

def __next__(self):
    if self.current == self.trailer:
        raise StopIteration
    result = self.current
    self.current = self.current.next
    return result
一旦我们修复了所有这些,我们就有了一个成功运行的代码。但是我们只得到以下输出:
['header','foo']
。当然,这不是我们想要的

发生这种情况的原因是,项目的实际顺序如下所示:

header
foo
trailer
baz
trailer
def __iter__(self):
    return LinkedListEnumerator(self)
(是的,有一个递归)显然,
append
毕竟不能正常工作。如果您只是附加了两个元素,您可以看到该元素被添加到拖车元素之后。这意味着,
self.current
确实命中了append循环中的拖车元素:

while self.current is not self.trailer:
    self.current = self.current.next
如果你看一下,这是有道理的:
self.current
首先更新,然后进行检查以最终取消循环。当时
self.current
self.trail
。因此,我们应该检查self.current.next,而不是:

while self.current.next is not self.trailer:
    self.current = self.current.next
一旦我们解决了这个问题,我们就会得到以下输出:
['header'、'foo'、'bar'、'baz']
。这几乎是我们希望看到的。我们现在需要做的就是跳过header元素。我们只需从标题后面的元素开始:

def __iter__(self):
    self.current = self.header.next
    return self
然后它就起作用了


这就是让代码运行所需要的全部然而,我通常建议不要使用这种方法。您正在列表中存储迭代状态,这是非常脆弱的。你应该尽可能地让这个州成为当地人

特别是,链表不需要既是可枚举的又是枚举器。实现
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
实现前者,实现
实现后者。Enumerable表示“您可以迭代这个东西”,而枚举器是执行迭代的东西,并且具有迭代状态

尝试将迭代状态从链表中移出,使其仅可枚举,而不是枚举器。为此,请添加一个引用列表并跟踪当前元素的
LinkedListNumerator
类型:

class LinkedListEnumerator:
    def __init__ (self, lst):
        self.lst = lst
        self.current = lst.header.next

    def __iter__ (self):
        return self

    def __next__ (self):
        if self.current == self.lst.trailer:
            raise StopIteration
        result = self.current
        self.current = self.current.next
        return result
然后,您可以删除链接列表中的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法,并用以下方法替换
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

header
foo
trailer
baz
trailer
def __iter__(self):
    return LinkedListEnumerator(self)

然后你就不再有链接列表中的状态了。(此时,您还应该在
append
中将
current
设置为局部变量,并完全删除
self.current

那么,您是否在没有任何值的情况下初始化了链接列表?似乎即使没有任何值,它的大小也是2。这就是您想要的吗?另外,您通常希望节点存储关于下一个和上一个节点的状态。链表用于添加/删除和遍历。它不必担心节点之间的关系。@Coldspeed头部和尾部是这里的一个实现细节。那太好了。此外,我看不出列表在哪里担心节点之间的关系。修改列表时,必须重新链接某些元素。我认为OP的一般方法没有任何错误。@poke我假设“链表”意味着节点类具有self.next和self.prev。嗯,我需要更深入地看看这个…:-)@是的,没错。这就是OP的代码存在的问题之一:PWow!非常感谢你!我认为我的很多问题都源于对我的问题从哪里开始的缺乏了解。另外,我真的很感激你解释为什么我采取的方法不是最佳的;我得到的最好的解释!