【问题标题】:Python comma assignments order [closed]Python逗号分配顺序[关闭]
【发布时间】:2021-07-14 22:41:03
【问题描述】:

我正在尝试使用 Python 逗号赋值来并行更改变量的值。我相信 Python 会首先评估右侧表达式的值,然后将这些值分配给左侧的变量。一个具体的例子就是这个反向链表代码:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        prev = None
        curr = head
        while curr != None:
            prev, curr.next, curr = curr, prev, curr.next
        return prev

prev, curr.next, curr = curr, prev, curr.next 工作得很好。如果我将顺序更改为prev, curr, curr.next = curr, curr.next, prev,我希望我的代码可以正常工作:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        prev = None
        curr = head
        while curr != None:
            prev, curr, curr.next = curr, curr.next, prev
        return prev

但是,我在该行的第二个代码中得到了一个错误:

AttributeError: 'NoneType' object has no attribute 'next'
    prev, curr, curr.next = curr, curr.next, prev

这对我来说没有意义,因为 Python 在赋值之前首先评估右侧表达式,这意味着我放置表达式的顺序无关紧要。我在这里遗漏了什么吗?

【问题讨论】:

  • 请在您的问题中编辑您的代码,使其成为minimal reproducible example - 任何人都应该能够将单个复制/粘贴到文件中并且不添加任何东西 运行它以查看您看到的相同问题。因此,您需要包含导入、数据和所有引用的函数/类。确保在将代码编辑到您的问题中后,您可以按照我描述的方式运行您的代码。
  • 如果将 None 分配给 curr,curr.next 将引发错误。
  • 如果您在任何时候评估和分配 RHS 中的元组 (somenode, None, someothernode) 到 prev, curr, curr.next 那么在 curr.next 之前分配的 curr 指针变为 None当您尝试分配 curr.next 时会引发错误
  • 可怕的想法。使您的代码易于人们阅读。技巧表明缺乏经验。

标签: python linked-list singly-linked-list


【解决方案1】:

你是正确的,Python首先评估右侧;但是,缺少的是 Python 将按顺序评估每一边。我们可以通过将两个选项分解为单独的赋值语句 (Full example on Hastebin) 来了解这意味着什么:

# First example:
def reverseList(head: ListNode) -> ListNode:
    prev = None
    curr = head
    while curr != None:
        # prev, curr.next, curr = curr, prev, curr.next
        x = curr
        y = prev
        z = curr.next
        prev = x
        curr.next = y
        curr = z
    return prev
# Second example:
def reverseList2(head: ListNode) -> ListNode:
    prev = None
    curr = head
    while curr != None:
        # prev, curr, curr.next = curr, curr.next, prev
        x = curr
        y = curr.next
        z = prev
        prev = x
        curr = y
        curr.next = z
    return prev

这里的重要部分是,在第一个示例中,我们分配了curr.next 的值我们分配了curr 的值,而在第二个示例中我们分配了@ 的值987654328@ 之后。这意味着当我们分配curr.next 时,我们已经更新了curr,所以当解释器再次访问curr.next 进行另一个分配时,它会拉回错误的引用。当您将 curr 设置为 None 时会发生错误,然后在这样做之后,您尝试访问 curr.next 以完成重新分配操作。

附带说明,尽量不要使用next 作为变量名。由于它是一个内置函数,它可能会引起一些混乱,虽然它可能没问题。

【讨论】:

  • next 作为关键字的文档在哪里?在语法docs.python.org/3/reference/grammar.html 的任何地方都看不到
  • @balmy 在网上搜索“python next”时发现:Built-in functions 回答者没有说明它是关键字(afaik python 在意外使用关键字时会抛出语法错误方式),而是一个内置函数。
  • @exalted 编辑了它 - 用来说关键字不是内置的 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多