首页 > 解决方案 > 在 Python 中交换三个对象。为什么顺序相关?

问题描述

我想更好地了解三个对象的交换如何在 Python 中工作。我很好奇使用以下语法交换对象及其属性时顺序如何影响结果。

left, right, right.attr = right, left.attr, right 

特别是,我有以下代码要反转链表:

class Solution(object):                                                            
    def reverseList(self, head):                                                   
        """                                                                        
        :type head: ListNode                                                       
        :rtype: ListNode                                                           
        """                                                                        
        if not head or not head.next: 
            return head                                  

        prev, cur = None, head                                                     
        while cur:
            cur, prev = swap(cur, prev)                                                                                                                                                                      
        return prev

我正在考虑两个swap函数,每个函数都有不同的重新分配对象的顺序:

def swap_bad(cur, prev):
    prev, cur, cur.next = cur, cur.next, prev 
    return cur, prev

def swap_good(cur, prev):
    cur.next, cur, prev = prev, cur.next, cur
    return cur, prev

我希望这两个函数是等效的,但是正如名称所暗示的那样,第一个不起作用,而第二个起作用。你能解释一下为什么会这样吗?

标签: python

解决方案


这是 Python 执行命令的顺序示例。

设置如下:

class Test:
    def __init__(self, name, nxt=None):
        self.name = name
        self.nxt = nxt

    def __str__(self):
        nxt = self.nxt.name if self.nxt is not None else None
        return f"Test(name={self.name}, nxt={nxt})"


prev = Test(0)
cur = Test(1, prev)

def swap_good(cur, prev):
    cur.nxt, cur, prev = prev, cur.nxt, cur

def swap_bad(cur, prev):
    prev, cur, cur.nxt = cur, cur.nxt, prev

确实输出是不同的:

swap_good(cur, prev)
print(cur)
print(prev)
# Test(name=1, nxt=0)
# Test(name=0, nxt=None)

# re-initialize cur, prev as above
swap_bad(cur, prev)
print(cur)
print(prev)
# Test(name=1, nxt=0)
# Test(name=0, nxt=0)  # nxt=0 instead of nxt=None

拆解函数

from dis import dis
dis(swap_good)
dis(swap_bad)

swap_good

 20           0 LOAD_FAST                1 (prev)
              2 LOAD_FAST                0 (cur)
              4 LOAD_ATTR                0 (nxt)
              6 LOAD_FAST                0 (cur)
              8 ROT_THREE
             10 ROT_TWO
             12 LOAD_FAST                0 (cur)
             14 STORE_ATTR               0 (nxt)
             16 STORE_FAST               0 (cur)
             18 STORE_FAST               1 (prev)
             20 LOAD_CONST               0 (None)
             22 RETURN_VALUE

并且对于swap_bad

 35           0 LOAD_FAST                0 (cur)
              2 LOAD_FAST                0 (cur)
              4 LOAD_ATTR                0 (nxt)
              6 LOAD_FAST                1 (prev)
              8 ROT_THREE
             10 ROT_TWO
             12 STORE_FAST               1 (prev)
             14 STORE_FAST               0 (cur)
             16 LOAD_FAST                0 (cur)
             18 STORE_ATTR               0 (nxt)
             20 LOAD_CONST               0 (None)
             22 RETURN_VALUE

您可以看到不同之处(查找操作码,您可以弄清楚这里到底发生了什么;诚然,我很懒惰这样做,但这应该可以帮助您入门)。


推荐阅读