【问题标题】:is this a good way to maintain a temporary variable that a method need as an instance variables?这是维护方法需要作为实例变量的临时变量的好方法吗?
【发布时间】:2021-05-25 14:42:15
【问题描述】:

我创建了一个 Node 类和一个 LinkedList 类:

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


class LinkedList:
    def __init__(self):
        self.last_node = Node(0)
        self.start_node = self.last_node
        
    def add(self, item):
        new_node = Node(item)
        new_node.next = None

        self.last_node.next = new_node
        self.last_node = new_node
        
        return new_node

我想实现一种方法来递归返回链表的长度。 所以我添加了一个新的实例变量(i)来维护当前节点。 这是带有 len 函数的最终代码:

class LinkedList:
    def __init__(self):
        self.last_node = Node(0)
        self.start_node = self.last_node
        self.i = self.start_node
    def add(self, item):
        new_node = Node(item)
        new_node.next = None

        self.last_node.next = new_node
        self.last_node = new_node
        
        return new_node

    def len(self):
        if self.i.next == None:
            return 0
        self.i = self.i.next
        return 1 + self.len()
l = LinkedList()
head = l.add(1.5)
l.add("3hh")
l.add(5)
l.len()//result is 3

这是(将其保存为实例变量)维护函数需要的临时变量的最佳方式吗?

【问题讨论】:

  • 就像注释一样,您可以通过添加方法 def __len__(self): return self.length_function() 使您的类使用 python 长度函数。然后你可以做 len(l) 而不是 l.len()

标签: python recursion linked-list


【解决方案1】:

没有。这根本不是最好的方法,因为如果我在同一个列表上两次调用len,我会得到两个不同的答案。不仅如此,而且您的原始实现给出了错误的答案,因为您的 __init__ 方法创建了一个包含 1 个元素而不是空列表的列表(因此您的测试用例列表实际上的长度为 4)。正确的做法如下:

def len(self):
    def node_len(node):
        return 0 if node is None else 1 + node_len(node.next)
    return node_len(self.start_node)

这反映了一般原则,如果您需要一些额外的信息,您应该将额外的信息作为输入传递给函数。在这种情况下,我们会将您存储在 self.i 中的额外信息作为输入传递给我们的辅助函数,这样我们就可以在不改变列表的情况下计算列表的长度。

【讨论】:

  • 哇,我看到了编程的一个新领域。谢谢你。这种东西(比如辅助函数)是设计模式的概念吗?你能介绍一本书吗?
  • @usf 很高兴您发现这很有帮助!有一种将数据传递给函数的通用编码模式——不过我不知道我是否称它为设计模式。如果您想了解更多关于这类事情的信息,我建议您研究函数式编程。我不知道有什么好的 Python 书籍,但如果你愿意学习 Scheme 并处理一些具有挑战性的材料,那么总会有经典的 SICP。如果你想在这方面做到真正的硬核,你可以尝试学习 Haskell(但我不知道有什么好书)。
【解决方案2】:

虚拟节点通常用于简化实现链表的逻辑,因为它确保链表始终由Node 实例组成,而不是使用None 表示空列表。虚拟节点中的“数据”可以任意使用,例如存储列表的长度。

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

class LinkedList:
    def __init__(self):
        self.last_node = self.head = Node(0)
        
        
    def add(self, item):
        new_node = Node(item)
        new_node.next = None

        self.last_node.next = new_node
        self.head.item += 1

    def len(self):
        return self.head.item

removedelete 方法同样会减少 self.head.item

【讨论】:

    猜你喜欢
    • 2020-10-10
    • 2017-02-15
    • 2021-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-18
    • 1970-01-01
    相关资源
    最近更新 更多