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的維度。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM