一个关于Python中LinkedList实现的删除功能的问题

时间:2020-06-28 14:47:14

标签: python

我正在用Python编写LinkedList的实现。在remove函数中,该函数按索引删除项目。删除列表中的第一个节点时,发现一个local variable is not used问题:

class LinkedList:
    def __init__(self, nodes=None):
        self.head = None

    def remove(self, index):
        pre_node = self.head
        if index == 0:
            self.head = self.head.next
            # next line doesn't work
            # pre_node = self.head.next 
            return
        for idx, cur_node in enumerate(self):
            if idx == index-1:
                pre_node = cur_node
            if idx == index:
                pre_node.next = cur_node.next
                return
        raise Exception('index out of range')

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

    def __str__(self):
        node = self.head
        nodes = []
        while node is not None:
            nodes.append(node.data)
            node = node.next
        nodes.append("None")
        return '->'.join(nodes)

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

if __name__ == '__main__':
    first_list = LinkedList()
    first_node = LinkedList.Node('0')
    first_list.head = first_node
    second_node = LinkedList.Node('1')
    first_node.next = second_node
    third_node = LinkedList.Node('2')
    second_node.next = third_node
    first_list.remove(0)
    print(first_list)

假设列表是0->1->2->None的种类,则在调用a_list.remove(0)时,它应返回1->2->None。上面带有语句self.head = self.head.next的代码运行良好,而self.head = pre_node.next也运行良好,但是pre_node = pre_node.nextpre_node = self.head.nextpre_node is not used失败,该函数返回了原始清单。我很困惑,为什么代码应该只在赋值左侧的self.head而不是pre_node正确,即使我们在此之前做pre_node = self.head

1 个答案:

答案 0 :(得分:1)

一个局部变量(如pre_node)仅存在,直到您从函数return开始。所以在这段代码中:

            self.head = self.head.next
            pre_node = self.head.next 
            return

pre_node = self.head.next行没有任何用处,因为您设置的变量会在返回时消失。这实际上并不会导致程序失败,但是linters和IDE会在看到类似这样的内容时向您发出警告,因为这表明您错过了某些内容(例如,您打算将其设置为实例变量,或者您打算进行其他操作)具有该值)。

在这种情况下,您已经完成了删除节点所需的操作,即重新分配self.head。由于pre_node = self.head.next行不执行任何操作,因此您可以在不更改程序工作方式的情况下将其删除。这里没有真正的问题(至少对于index == 0而言)。

使用局部变量的地方将是引用列表中需要修改的其他节点的一种方式。例如:

def remove(self, index):
    """Remove the node with the given index.
    Raises AttributeError if the index is out of range."""
    if index == 0:
        # Move self.head pointer up one to remove head node.
        self.head = self.head.next
        return
    # Find node before the one with the given index.
    pre_node = self.head
    for _ in range(index-1):
        pre_node = pre_node.next
    # Remove pre_node.next by skipping over it.
    pre_node.next = pre_node.next.next

在此代码中,pre_node引用了列表中的特定节点,您可以通过重新分配pre_node.next来对其进行修改。函数完成后,变量pre_node本身并不重要,但是它引用的节点是列表的一部分,因此重新分配pre_node.next会对列表产生影响,其方式为重新分配{{ 1}}本身就没有。