zoukankan      html  css  js  c++  java
  • Python for 循环中使用append()添加可变元素,前面的值被覆盖,循环中内存应用地址不变

    在使用list.append(a), 添加动态改变的a(a = random.random())时,发现循环中每一个新的循环改变的a会在list中把之前的值全部改变;

    查找后自了,Python是基于对象引用的,append添加的是一个“地址、引用”,当这个地址内的内容改变时,前面的同“地址”的内容都改变。

    查看“内存、应用”’使用      id(object).

    简单的就不啰嗦了网上关于地址内存都有介绍,经过测试后发现,一般情况下给变量  一个新值时这个id就会改变,当然这个值若是和以前

    相同这个id就一样。在for循环中这个情况就不一样

    import random
    def test():
        return random.random()
    
    def test1():
        for i in range(3):
            for i in range(2):
                a = test()
                print('a_id=',id(a))

    结果是

    a_id= 2566513744848
    a_id= 2566513744872
    
    a_id= 2566513744848
    a_id= 2566513744872
    
    a_id= 2566513744848
    a_id= 2566513744872

    可以看到内存分配时,对应内层2次循环的给了2个2个地址,节省开支;  如果是这样的话使用list.append()最后就只有6个元素2个结果,

    但是

    import random
    
    list_a = []
    list = [1,2,3,4,5,6]
    
    
    def test():
        return random.random()
    
    def test1():
        for i in range(3):
            for i in range(2):
                a = test()
                print('a_id=',id(a))
                list_a.append(a)
        print(list_a)
    
    test1()

    结果

    a_id= 2566513744824
    a_id= 2566513744848
    a_id= 2566513744968
    a_id= 2566513744992
    a_id= 2566513745016
    a_id= 2566513745040
    
    [0.5481244502902065, 0.7452961787111314, 0.6038274060224955, 0.8269310521431017, 0.4091898711994284, 0.45233748625853376]

    可以看到地址都改变了,Python在运行时又分配的新的地址、引用,所以前面的数值没有变化。

    说了怎么多还没有到问题的重点;

    import random
    
    list_a = []
    list = [[1,1,0,1,0], [1,0,1,1,1]]
    
    def mutation(array):
        array.append(random.randint(1,10))
        return array
    
    def test2():
        for num in list:
            for i in range(3):
                a = mutation(num)
                print(a)
                print('a_id=',id(a))
                list_a.append(a)
        print(list_a)
    
    test2()
    [1, 1, 0, 1, 0, 8]
    a_id= 2566513576904
    [1, 1, 0, 1, 0, 8, 10]
    a_id= 2566513576904
    [1, 1, 0, 1, 0, 8, 10, 3]
    a_id= 2566513576904
    [1, 0, 1, 1, 1, 3]
    a_id= 2566515364744
    [1, 0, 1, 1, 1, 3, 5]
    a_id= 2566515364744
    [1, 0, 1, 1, 1, 3, 5, 4]
    a_id= 2566515364744
    
    [[1, 1, 0, 1, 0, 8, 10, 3],
     [1, 1, 0, 1, 0, 8, 10, 3],
     [1, 1, 0, 1, 0, 8, 10, 3],
     [1, 0, 1, 1, 1, 3, 5, 4],
     [1, 0, 1, 1, 1, 3, 5, 4], 
    [1, 0, 1, 1, 1, 3, 5, 4]]

    结果可以看到我向list中添加了一个新的值,但在list中元素的改变并不会改变list的id,内层3个循环中list的id始终不变,

    在加到list_a中的内层的3个循环中,始终是一个id,外层第一个循环结束后,取了此id的最后一个值,所以最后list_a的前3个值都相同。

    实际上网上一个list里加字典例子和这个道理是一样的,双层循环的内存循环了不改变id的对象,

    只是我写的时候把list变成其他形式了如([sum(list),,,]),找原因时也就看了id和转换的结果发现好多结果都一样,

    被其他的好多猜错试的好多,找了好久才发现原因。

    解决这个问题的办法是用copy,在

    mutation(array) 中copy要return的array产生一个新的id,(array = copy.copy(array)),
    至于是用浅拷贝还是深拷贝就要看array的维度。
  • 相关阅读:
    HDU 5486 Difference of Clustering 图论
    HDU 5481 Desiderium 动态规划
    hdu 5480 Conturbatio 线段树 单点更新,区间查询最小值
    HDU 5478 Can you find it 随机化 数学
    HDU 5477 A Sweet Journey 水题
    HDU 5476 Explore Track of Point 数学平几
    HDU 5475 An easy problem 线段树
    ZOJ 3829 Known Notation 贪心
    ZOJ 3827 Information Entropy 水题
    zoj 3823 Excavator Contest 构造
  • 原文地址:https://www.cnblogs.com/liuda9495/p/7657114.html
Copyright © 2011-2022 走看看