• 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)

  • 相关阅读:
    ADF中遍历VO中的行数据(Iterator)
    程序中实现两个DataTable的Left Join效果(修改了,网上第二个DataTable为空,所处的异常)
    ArcGIS api for javascript——鼠标悬停时显示信息窗口
    ArcGIS api for javascript——查询,然后单击显示信息窗口
    ArcGIS api for javascript——查询,立刻打开信息窗口
    ArcGIS api for javascript——显示多个查询结果
    ArcGIS api for javascript——用图表显示查询结果
    ArcGIS api for javascript——查询没有地图的数据
    ArcGIS api for javascript——用第二个服务的范围设置地图范围
    ArcGIS api for javascript——显示地图属性
  • 原文地址:https://www.cnblogs.com/ECJTUACM-873284962/p/8530459.html
Copyright © 2020-2023  润新知