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

2025-03-21 09:07:00
admin
原创
57
摘要:问题描述:我认为两者是相同的。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 = [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:

先决条件- 2 个要点

  • 列表是可变的

列表的主要部分是列表是可变的。这意味着列表的值可以更改。这是您遇到麻烦的原因之一。请参阅文档了解更多信息

  • 评估顺序

另一部分是,在解包元组时,求值从左到右开始。请参阅文档了解更多信息


介绍

当您执行时,和a,b = c,d的值首先被存储。然后从左侧开始,的值首先更改为,然后的值更改为。c`dacbd`

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


用例

现在来谈谈你的问题

在第一种情况下,

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

nums[0]最初为1,并且nums[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:

你可以定义一个类来跟踪这个过程:

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:

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

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

它首先将 分配nums[0]nums[nums[0]]平均值nums[1]==1,然后由于列表是可变对象,因此数字将是:

[1,1,0]

然后nums[nums[0]]将分配给nums[0]这意味着nums[0]==2和:

nums = [2,1,0]

第二部分也是如此。

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

评估顺序

Python 从左到右计算表达式的值。请注意,在计算赋值时,先计算右侧的值,然后再计算左侧的值。

解决方案 4:

在第一个例子中,正如您所预料的那样,nums[1] 被设置为 1,然后 nums[0] 被设置为 2。

在第二个例子中,nums[0] 被设置为 2,然后nums[2]被设置为 1。这是因为,在这种情况下,当赋值发生时,左边的 nums[nums[0]] 实际上引用的是 nums[2],因为 nums[0] 刚刚被设置为 2。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用