当前位置:  开发笔记 > 编程语言 > 正文

元组解包顺序更改分配的值

如何解决《元组解包顺序更改分配的值》经验,为你挑选了3个好方法。

我认为两者是相同的.

nums = [1, 2, 0]    
nums[nums[0]], nums[0] = nums[0], nums[nums[0]]    
print nums  # [2, 1, 0]

nums = [1, 2, 0]    
nums[0], nums[nums[0]] = nums[nums[0]], nums[0]    
print nums  # [2, 2, 1] 

但结果却不同.
为什么结果不同?(为什么会产生第二个?)



1> Bhargav Rao..:

先决条件 - 2个要点

列表是可变的

列表中的主要部分是列表是可变的.这意味着可以更改列表的值.这就是你遇到麻烦的原因之一.有关详细信息,请参阅文档

评估顺序

另一部分是在解包元组时,评估从左到右开始.有关详细信息,请参阅文档


介绍

当你执行a,b = c,d的值cd首次存储时.然后从左侧开始,首先将值a更改为c,然后将值b更改为d.

这里的问题是,如果b在改变值的同时对位置有任何副作用a,则将d其分配给后者 b,这是b受副作用的影响a.


用例

现在来解决你的问题

在第一种情况下,

nums = [1, 2, 0]    
nums[nums[0]], nums[0] = nums[0], nums[nums[0]]    

nums[0]最初是1nums[nums[0]]2因为它的计算结果nums[1].因此1,2现在存储在内存中.

现在,元组拆包从左侧发生,所以

nums[nums[0]] = nums[1] = 1   # NO side Effect. 
nums[0] = 2

因此print nums将打印[2, 1, 0]

但是在这种情况下

nums = [1, 2, 0]   
nums[0], nums[nums[0]] = nums[nums[0]], nums[0]    

nums[nums[0]], nums[0] 就像第一种情况一样,将2,1放在堆栈上.

然而,在左侧,也就是说 nums[0], nums[nums[0]],改变nums[0]具有副作用,因为它被用作索引nums[nums[0]].从而

nums[0] = 2
nums[nums[0]] = nums[2] = 1  # NOTE THAT nums[0] HAS CHANGED

nums[1]价值保持不变2.因此print nums将打印[2, 2, 1]



2> eph..:

您可以定义一个类来跟踪该过程:

class MyList(list):
    def __getitem__(self, key):
        print('get ' + str(key))
        return super(MyList, self).__getitem__(key)
    def __setitem__(self, key, value):
        print('set ' + str(key) + ', ' + str(value))
        return super(MyList, self).__setitem__(key, value)

对于第一种方法:

nums = MyList([1, 2, 0])
nums[nums[0]], nums[0] = nums[0], nums[nums[0]]

输出是:

get 0
get 0
get 1
get 0
set 1, 1
set 0, 2

而第二种方法:

nums = MyList([1, 2, 0])
nums[0], nums[nums[0]] = nums[nums[0]], nums[0]

输出是:

get 0
get 1
get 0
set 0, 2
get 0
set 2, 1

在这两种方法中,前三行与元组生成相关,而后三行与赋值相关.第一种方法的右侧元组是(1, 2)第二种方法(2, 1).

在分配阶段,第一种方法得到nums[0],其是1,和设置nums[1] = 1,然后nums[0] = 2,第二种方法分配nums[0] = 2,然后得到nums[0]其是2,最后设置nums[2] = 1.



3> Kasramvd..:

这是因为python赋值优先级从左到右.所以在下面的代码中:

 nums = [1, 2, 0]
 nums[nums[0]], nums[0] = nums[0], nums[nums[0]]

它首先分配了nums[0]to nums[nums[0]]means nums[1]==1,然后由于列表是可变对象,nums将是:

[1,1,0]

然后nums[nums[0]]将分配给nums[0]哪些方式nums[0]==2和:

nums = [2,1,0]

就像第二部分一样.

请注意,重要的一点是列表对象是可变的,当您在一段代码中更改它时,它可以就地更改.因此它会影响其余的代码.

评估订单

Python从左到右评估表达式.请注意,在评估分配时,右侧在左侧之前进行评估.

推荐阅读
N个小灰流_701
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有