Python 逗号赋值顺序
Python comma assignments order
我正在尝试 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 在赋值之前首先计算右侧的表达式,这意味着我放置表达式的顺序无关紧要。我在这里遗漏了什么吗?
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
的值,而在第二个例子我们赋值curr.next
之后。这意味着当我们去赋值 curr.next
时,我们已经更新了 curr
,所以当解释器再次访问 curr.next
进行另一个赋值时,它会拉回错误的引用。当您将 curr 设置为 None
,然后在这样做之后,您尝试访问 curr.next
以完成重新分配操作时,就会发生错误。
旁注,尽量避免使用 next
作为变量名。由于它是一个内置函数,因此可能会引起一些混乱,尽管它可能没问题。
我正在尝试 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 在赋值之前首先计算右侧的表达式,这意味着我放置表达式的顺序无关紧要。我在这里遗漏了什么吗?
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
的值,而在第二个例子我们赋值curr.next
之后。这意味着当我们去赋值 curr.next
时,我们已经更新了 curr
,所以当解释器再次访问 curr.next
进行另一个赋值时,它会拉回错误的引用。当您将 curr 设置为 None
,然后在这样做之后,您尝试访问 curr.next
以完成重新分配操作时,就会发生错误。
旁注,尽量避免使用 next
作为变量名。由于它是一个内置函数,因此可能会引起一些混乱,尽管它可能没问题。