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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Android4.0 input事件输入流程详解(中间层到应用层)

    Android4.0 input事件输入流程详解(中间层到应用层)在Android系统中,类似于键盘按键、触摸屏等事件是由WindowManagerService服务来管理的,然后再以消息的形式来分发给应用程序进行处理。系统启动时,窗口管理服务也会启动,该服务启动过程中,会通过系统输入管理器InputManager来负责监控键盘消息。当某一个Activity激活时,会在该Service下注册一个接收消息的通道,表明可以处理具体的消息,然后当有消息时,InputM

    2022年5月29日
    39
  • Android View 深度分析requestLayout、invalidate与postInvalidate「建议收藏」

    Android View 深度分析requestLayout、invalidate与postInvalidate「建议收藏」前言前几篇文章中,笔者对View的三大工作流程进行了详细分析,而这篇文章则详细讲述与三大工作流程密切相关的两个方法,分别是requestLayout和invalidate,如果对Viwe的三个工作流程不熟悉的读者,可以先看看前几篇文章,以便能更容易理解这篇文章的内容。

    2022年6月2日
    35
  • yolo 实例分割_jacobi椭圆函数

    yolo 实例分割_jacobi椭圆函数Abstract我们提出了一个简单的、完全卷积的实时实例分割模型,在MS-COCO上达到29.8map,在单个TitanXp上以33.5fps的速度进行评估,这比以往任何竞争方法都要快得多。而且,我们只在一个GPU上训练就得到了这个结果。我们通过将实例分割分成两个子任务来实现这一点:(1)生成一组原型掩码;(2)预测每个实例的掩码系数。然后,我们通过将原型与掩码系数结合起来,生成实例mask…

    2022年8月23日
    11
  • 通过nginx转发WebSocket

    通过nginx转发WebSocket通过nginx请求wensocket的时候需要修改配置文件,对于websocket请求需要特殊处理一下,需要在conf配置文件中添加一些配置:server{listen8080;server_nametest.com;add_header’Access-Control-Allow-Origin”*’always;add_header’Access-Control-Allow-Credentials”true’;add_header’A

    2022年10月18日
    2
  • navcat 15 激活码_在线激活[通俗易懂]

    (navcat 15 激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~S…

    2022年3月26日
    62
  • resnet网络结构示意图_resnet50网络结构详解

    resnet网络结构示意图_resnet50网络结构详解代码importtorchfromtorchimportnnimporttorchvisiondevice=torch.device(“cuda”iftorch.cuda.is_available()else”cpu”)resnet=torchvision.models.resnet101(pretrained=True)#pretrainedImageNetResNet-101print(resnet)输出:ResNet((conv1):Con

    2022年10月7日
    3

发表回复

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

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