【问题标题】:how is the object using a variable which is not inside the class or defined anywhere对象如何使用不在类内或在任何地方定义的变量
【发布时间】:2021-05-22 06:03:27
【问题描述】:

在这段代码中,类 Node 的对象正在使用一个未在任何地方定义的变量 next 并且代码仍在工作如何?对象如何使用未在其类中定义的变量

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

class LinkedList:

    # Function to initialize head
    def __init__(self):
        self.head = None

    # Function to reverse the linked list
    def reverse(self):
        prev = None
        current = self.head
        while(current is not None):
            next = current.next
            current.next = prev
            prev = current
            current = next
        self.head = prev

    # Function to insert a new node at the beginning
    def push(self, new_data):
        new_node = Node(new_data)
        new_node.next = self.head
        self.head = new_node

    # Utility function to print the linked LinkedList
    def printList(self):
        temp = self.head
        while(temp):
            print(temp.data)
            temp = temp.next



llist = LinkedList()
llist.push(20)
llist.push(4)
llist.push(15)
llist.push(85)

print( "Given Linked List")
llist.printList()
llist.reverse()
print ("\nReversed Linked List")
llist.printList()

【问题讨论】:

  • “没有在任何地方定义” - 那么new_node.next = self.head呢?
  • 是的,这是我的问题。对象可以只使用未在其自己的类中定义的变量吗?
  • new_node.next = ... 没有“使用”任何东西,它在new_node 实例上定义了一个next 属性。看起来你可能会从阅读一个很好的关于类的基础教程中受益,这将帮助你澄清这些概念。 SO 并不是最好的地方。
  • 是的,我只是一个初学者,所以仍在尝试解决问题,谢谢顺便说一句

标签: python python-3.x oop linked-list


【解决方案1】:

虽然在大多数强类型语言中这是不可能的,但 Python 允许在创建实例并且构造函数运行之后定义实例属性。只要代码在定义之前不引用属性,就没有问题。另见:Can I declare Python class fields outside the constructor method?

在这种特殊情况下,以下代码会产生错误:

node = Node(42)
if node.next:  # Attribute error
    print("42 is not the last node")
else:
    print("42 is the last node")

但是,创建新节点实例的唯一位置是在 LinkedList 类的 push 方法中:

def push(self, new_data):
    new_node = Node(new_data)
    new_node.next = self.head
    self.head = new_node

如您所见,next 属性是在节点构建后立即定义的。所以在实践中,链表中的每个节点都会有一个next属性。

最佳实践?

这种编码实践是否可取尚有争议。例如,Pylint 有一条规则 defining-attr-methods,默认情况下,当属性定义在 __init____new__setUp__post_init__ 之外时,它会发出警告。

另类

在这种情况下,我当然更愿意在构造函数中定义next 属性,并为构造函数提供一个额外的可选参数,使用该参数可以初始化next

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

通过这一更改,LinkedList 类的 push 方法可以简化为:

class LinkedList:
    # ...

    def push(self, new_data):
        self.head = Node(new_data, self.head)

这样看起来优雅多了。

无关,但我也会让LinkedList 的构造函数接受任意数量的值来初始化列表:

class LinkedList:
    def __init__(self, *values):
        self.head = None
        for value in reversed(values):
            self.push(value)

现在主代码可以一次性创建一个包含 4 个值的列表:

llist = LinkedList(85, 15, 4, 20)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-05
    • 2019-06-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-05
    • 1970-01-01
    相关资源
    最近更新 更多