python變量內存淺析


1. Python變量

   如果把單一值變量稱為一維變量,把可以擴展元素的變量稱為多維變量,則python的變量可以划分如下:

變量維度

Python變量

說明

一維

數字

int(有符號整型)

數字類型可以做轉換

long(長整型[也可以代表八進制和十六進制])

float(浮點型)

complex(復數)

字符串

字符串有豐富的運算符和內嵌函數;

有格式化輸出;

二維

列表

除了元祖外,列表和字典可以靈活的擴展元素

元組

字典

2. Python變量的賦值處理

   這里主要分析情況為,將原始變量賦值給新變量后,二者的變化關聯情況,比如:原始變量為varold,新變量varnew = varold,之后varnew發生了變化,那么varold如何變化,二者的地址情況如何?這里給出測試用例:

   用例1

def whole_modify(value_old, value_new):
    #before
    obj_old = value_old
    obj_new = obj_old
    print(obj_old, id(obj_old))
    print(obj_new, id(obj_new))
    #after
    obj_new = value_new
    print(obj_old, id(obj_old))
    print(obj_new, id(obj_new))
print('value:')
whole_modify('aaa', 9)
print('list:')
whole_modify(['a', 2], [3, 'b'])
print('Dictionary:')
whole_modify({1:'a', 'b':2}, {3:'c'})

   測試結果:

value:

('aaa', 38126200)

('aaa', 38126200)

('aaa', 38126200)

(9, 4014992)

list:

(['a', 2], 43066072)

(['a', 2], 43066072)

(['a', 2], 43066072)

([3, 'b'], 41421080)

Dictionary:

({1: 'a', 'b': 2}, 39583440)

({1: 'a', 'b': 2}, 39583440)

({1: 'a', 'b': 2}, 39583440)

({3: 'c'}, 39599104)

   用例1whole_modify是對新變量的整體修改,即直接用=號將一個全新的數據整體賦值給新變量,從測試情況看,結論是:

   不論一維還是二維變量,通過=號整體賦值后,新變量會重新分配內存,值為新賦給的值;原變量保持不變。

   用例2

print("list:")
obj_old = ['a', 2]
obj_new = obj_old
print(obj_old, id(obj_old))
print(obj_new, id(obj_new))#after
obj_new[0] = 3
print(obj_old, id(obj_old))
print(obj_new, id(obj_new))

print("dictionary:")
obj_old = {1:'a', 'b':2}
obj_new = obj_old
print(obj_old, id(obj_old))
print(obj_new, id(obj_new))#after
obj_new['b'] = 'newvaluestr'
print(obj_old, id(obj_old))
print(obj_new, id(obj_new))

   測試結果:

list:

(['a', 2], 39932832)

(['a', 2], 39932832)

([3, 2], 39932832)

([3, 2], 39932832)

dictionary:

({1: 'a', 'b': 2}, 40107728)

({1: 'a', 'b': 2}, 40107728)

({1: 'a', 'b': 'newvaluestr'}, 40107728)

({1: 'a', 'b': 'newvaluestr'}, 40107728)

   用例2中,主要是對二維變量內部元素做修改(一維變量無需測試),從測試情況看,結論是:

   老二維變量被賦給新二維變量后,對二者任何一個的內部元素修改,二者的地址不會發生改變,但值會同步被修改。

3. 分析

   Python的變量賦值(包括傳參,返回參數等場景),與c/c++區別很大,而且很難用一句話概括其用法。上面兩個測試用例主要是從變量類型的角度來區分,具有很強代表性,可以引申到很多場景輔助理解。

   很多人將python的變量賦值當做引用看待,這應該是有問題的,比如上面用例1中,很顯然就不是引用,因為新變量地址和值都變化了,而老變量完全保持不變。而c/c++引用的概念是,新老變量地址不變,值同步變化。

   用例2中對二維變量做局部修改,會發現新老變量的局部元素的地址和值都同步變化了(變量本身地址不變),這個和引用相同的地方是值同步變化了,不同的是變量地址也同步變化了。

   Python的這種處理,應該是基於內存效率的考慮,雖然python應用開發中不用考慮變量地址與內存回收,但如果對變量賦值的內存情況完全忽視,則很容易產生意外的結果。


免責聲明!

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



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