python 內存地址賦值


python 沒有同 cpp 一樣的指針地址,所以使用起來其實蠻簡單的

int, string, tuple不可變類型

i = 9
str = 'te'
print(id(i), id(str))

j = i
str2 = str
print(id(j),id(str2))
94728568118848 139677717183600
94728568118848 139677717183600

可以看出,python對普通變量的處理,是直接將引用的物理地址賦值給另一個變量

如果修改其中的值,則該類型變量會重新分配空間,

str = '111'
print(id(str))

str2 = str
str2 = '222'
print(f'str={str},str2={str2}')
print(id(str), id(str2))
139737600922096
str=111,str2=222
139737600922096 139737601153136

dict, list 可變類型

該類型略有不同。舉例說 a = [1,2] 列表,內存有“兩層”地址,一層針對 a 通過id(a) 查看,另一層針對值 通過id(a[0]) 查看——
我況且暫稱為這是“二級地址”

而我們使用簡單的 y = a 這樣的賦值語句的時候,python會直接賦值一級地址,使得 id(y)=id(a), 避免了重復開辟內存復制一份
看例子:

mylist = [2,3,4]
mylist2 = mylist

print(id(mylist), id(mylist2))  # 兩者是相同的, 即mylist2指向了mylist的內存地址

mylist[2] = 999  # 所以可以看到修改了list2, 也修改了原有list
print(mylist)
print(mylist2)

print(id(mylist[2]), id(mylist2[2]))  # 兩者地址是相同的
140101330826944 140101330826944
[2, 3, 999]
[2, 3, 999]
140101573246704 140101573246704

再看一個例子以更好的理解:

mylist = [2,3,4]
mylist2 = mylist

mylist[2] = 999  # 所以可以看到修改了list2, 也修改了原有list

mylist2 = [-1, -2]  # mylist2 指向新的內存地址, 不影響原來的
print(mylist)  # [2, 3, 999]
print(mylist2)  # [-1, -2]
[2, 3, 999]
[-1, -2]

繼續舉例:
下面這個例子使用 copy.copy() 方法實現淺拷貝。淺拷貝(t = copy.copy(y))和直接復制 (t=y) 是有區別的。直接復制,即后者以及在上一個例子中闡述了,它會直接修改t指向y的物理地址,這樣就不用再開辟內存重新復制了。而淺拷貝,是重新開辟內存,將值重新復制一份。
那為什么叫做 “淺”呢?——相對的肯定會有“深”
因為復制拷貝的不夠充分。即值拷貝列表的一級地址,而不拷貝(開辟內存拷貝)二級地址的值。
比如,y = [1,2,3,['str','we']] ,t=copy.copy(y)淺拷貝只會為1,2,3 開辟內存,而['str','we']則使用偷懶的直接改變地址引用。
也就是說,一級地址我會開辟內存,面對二級地址(['str','we'])則偷懶,直接改地址指向的目標
具體看下:

import copy
lst = [1,2,3]
sourcelst = [9,99,lst]
copylst = copy.copy(sourcelst)  # 淺拷貝

print(id(sourcelst), '  ',id(copylst))  # 首id 不同,一級地址相同
print(id(sourcelst[0]), id(copylst[0]))  # 實際值內存相同,"二級地址"

print(sourcelst, '  ',copylst)

# test 1
lst.append(0)
print('===test 1:\n',sourcelst, copylst,'\n===')  # 均修改了, 因為lst[4] 是“二級地址”, 是公用的

# test 2
copylst.append('test 2')
print('===test 2:\n',sourcelst, copylst,'\n===')  # 因為淺拷貝, 而修改的是一級地址, 所以兩個結果不同
139683722987456    139683722987584
94417646587456 94417646587456
[9, 99, [1, 2, 3]]    [9, 99, [1, 2, 3]]
===test 1:
 [9, 99, [1, 2, 3, 0]] [9, 99, [1, 2, 3, 0]] 
===
===test 2:
 [9, 99, [1, 2, 3, 0]] [9, 99, [1, 2, 3, 0], 'test 2'] 
===

所以,為了避免以上問題,可以使用深拷貝,deepcopy

參考

https://www.cnblogs.com/Liubit/p/7668476.html
https://blog.csdn.net/dudu3332/article/details/103259085


免責聲明!

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



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