Python 并行赋值

经常可以在Python看到这样的赋值语句

a, b, c = 1, 2, 3,其执行顺序先执行=右边的表达式,再依次将值赋给左边,Python解释器会将其组成为一个tuple,赋值的时候再unpack。

1
2
3
4
>>> a, b = 2, 0
>>> a, b, a = 1, a, 4
>>> a, b
(4, 2)

可以看到,上面是先把算出右边的值(1, 2, 4)再将其赋值给左边,最后a的值被修改成了4。

如果是可变的对象怎么办,LeetCode有一道经典的题,叫反转一个链表。要求将1->2-3->None的链表反转成3->2->1->None
有一个迭代的写法是这样的。

1
2
3
4
5
6
7
8
def reverseList(head):
prev = None
while head:
cur = head
head = head.next
cur.next = prev
prev = cur
return prev

它的简化写法如下:

1
2
3
4
5
def reverseList(self, head):
prev = None
while head:
head.next, prev, head = prev, head, head.next
return prev

具体的过程是这样的。先执行=右边表达式(None, head, head.next),然后第一步把head.next=None,此时head变成了1->None;第二步,执行prev=head,这里为什么head的值时1->None而不是1->2-3->None呢,因为虽然等式先执行的右边,拿到了head,但是上一步的操作是将head修改了,由于head是一个可变对象,prev的值是1->None,最后再把head=head.next,这里为什么head.next的值又是2->3->None了呢,因为,执行右侧的表达式之后,head.next这个对象再前两步中没有被修改,一直都是2->3->None,这正是和第二步不同的地方,所以这两个写法是等同的。

参考: