python易错盲点排查之+=与+的区别分析以及一些赋值运算踩过的坑[通俗易懂]

python易错盲点排查之+=与+的区别分析以及一些赋值运算踩过的坑

大家好,又见面了,我是全栈君。

问题1. int和list是不一样的

 

>>> a=1
>>> b=a
>>> a+=1
>>> a,b
(2, 1)
>>> a=[1,2,3,4]
>>> b=a
>>> a+=[5]
>>> a,b
([1, 2, 3, 4, 5], [1, 2, 3, 4, 5])

 

通俗地讲,类型为int时,a和b是“不一样的”;类型为list时,a和b是“一样的”。术语叫做immutable和mutable,具体原理在这个节点不必深究。
问题1.1. 我们通常运行b=a这一语句时,会直觉地认为,b和a已经不一样了。

>>> a=[[1],[2],[3],[4]]
>>> b+=a[0:2]
>>> b
[1, 2, 3, 4, [1], [2]]
>>> a=[[1],[2],[3],[4]]
>>> b=[]
>>> b+=a[0:2]
>>> a,b
([[1], [2], [3], [4]], [[1], [2]])
>>> b[0]
[1]
>>> b[0][0]='changed!'
>>> # You don't expect a to change
>>> # However
>>> a, b
([['changed!'], [2], [3], [4]], [['changed!'], [2]])

可以看到,a[0]的[1]和b[0]的[1]是“一样的”,因为改变b[0]就会改变a[0](注意不是改变b,是改变b[0]。改变b不会对a有任何影响)
问题2. list的情况下,a+=b和a=a+b是不一样的

>>> a=[1,2,3,4]
>>> b=a
>>> a+=[5]
>>> a,b
([1, 2, 3, 4, 5], [1, 2, 3, 4, 5])
>>> a=[1,2,3,4]
>>> b=a
>>> a=a+[5]
>>> a,b
([1, 2, 3, 4, 5], [1, 2, 3, 4])

同样通俗地讲,在+=的情况下,a还是原来的a,和b“一样”;在+的情况下,a已经不是原来的a了,和b“不一样”。
问题3. 如果要让+=和+行为一致,应该怎么做?

>>> import copy
>>> a=[1,2,3,4]
>>> b=copy.deepcopy(a)
>>> a+=[5]
>>> a,b
([1, 2, 3, 4, 5], [1, 2, 3, 4])

这与问题2中a=a+b的情况结果一致了。当对list进行b=a时,实际上进行的是“引用”操作;只有使用b=copy.deepcopy(a)才是进行我们通常期望的“拷贝”操作。
问题4. 回到问题中的代码,当k=1时,以下代码:

subset += (elements[0:size])

根据问题1.1,subset与elements是“一样的”,因此未来改变subset的元素的操作有可能改变elements的元素

到这行代码时,注意set就是递归传递过来的subset:

#set[j] +=  (elements[i])  #Why Elements change here?
set[j]  = set[j] +  (elements[i]) 

根据问题2,+=中set[j]依然是原来的set[j],也就可能是elements的元素。因此

set[j] += elements[i]

可能会等价于

elements[*] += elements[i]

一旦改变了elements的元素,结果自然就不对了。
怎么解决这个问题?根据问题3,只要保证set与elements是“不一样的”,就符合程序的逻辑。因此将

subset += (elements[0:size])

改为(记得import copy)

subset += copy.deepcopy(elements[0:size])

就能在+=的情况下正常运行了。
总结:python中,list类型的赋值b=a进行的引用操作,而非拷贝操作,在需要拷贝操作时,需要加上b=copy.deepcopy(a)。(copy.copy和copy.deepcopy的区别超出问题范畴,有兴趣可以google)

 

转载于:https://www.cnblogs.com/ECJTUACM-873284962/p/8530459.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/107664.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Python迭代器

    为方便日后查询和学习,关于Python迭代器的内容将从可迭代对象、迭代器和从迭代器到序列三个方面总结1.可迭代对象a.Python中经常使用for…in…来对某个对象进行遍历,此时被遍

    2021年12月18日
    39
  • 实型变量_C语言实型常数的合法形式

    实型变量_C语言实型常数的合法形式实型变量分为两类:单精度型和双精度型,其类型说明符为float单精度说明符,double双精度说明符。在TurboC中单精度型占4个字节(32位)内存空间,其数值范围为3.4E-38~3.4E+38,只能提供七位有效数字。双精度型占8个字节(64位)内存空间,其数值范围为1.7E-308~1.7E+308,可提供16位有效数字。实型变量说明的格式和书写规则与整型相同。例如:f

    2025年8月25日
    0
  • EasyTouch基本用法

    EasyTouch基本用法EasyTouch基本用法本文提供全流程,中文翻译。Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验——高分辨率用户请根据需求调整网页缩放比例)1hierarchy(层次面板)

    2022年8月2日
    5
  • 移动端网页设计_redis client命令

    移动端网页设计_redis client命令一、服务器与客户端的交互Redis服务器是典型的一对多服务器程序:一个服务器可以与多个客户端建立网络连接,每个客户端可以向服务器发送命令请求,而服务器则接收并处理客户端发送的命令请求,并向客户端返回命令回复 Redis服务器通过使用由I/O多路复用技术实现的文件事件处理器,Redis服务器使用单线程单进程的方式来处理命令请求,并与多个客户端进行网络通信clients属性stru…

    2022年10月9日
    3
  • api接口token验证

    api接口token验证

    2021年10月13日
    118
  • 一小时搞定 简单VBA编程 Excel宏编程快速扫盲

    一小时搞定 简单VBA编程 Excel宏编程快速扫盲Excel宏编程可以快速完成批量表格操作:复制粘贴、数据过滤等,宏代码基于VB语言实现,有基础的编程经验就能快速阅读。下面是我的学习笔记。1.ExcelVBA编辑界面(进入路径:sheet名称–>鼠标右键菜单–>查看代码)2.输入代码方法:在VBE编辑器的代码模块中输入VBA代码,通常有以下几种方法:■手工键盘输入;■使用…

    2022年4月27日
    53

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号