在Python中交换三个对象。订单为何相关?

时间:2019-06-19 07:07:30

标签: 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

我希望这两个功能是等效的,但是顾名思义,第一个功能不起作用,而第二个功能可以起作用。您能否阐明为什么会这样?

1 个答案:

答案 0 :(得分:0)

这是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

您可以看到不同之处(查找op-codes可以了解这里的实际情况;我很乐意这样做,但这应该可以帮助您入门)。