python的變量,對象的內存地址以及參數傳遞過程


作為一個由c/c++轉過來的菜鳥,剛接觸Python的變量的時候很不適應,應為他的行為很像指針,void* ,不知道大家有沒有這樣的感覺。其實Python是以數據為本,變量可以理解為標簽。作為c/c++的菜鳥,把跟蹤變量地址的習慣帶入Python,舉個小例子說明Python的變量,對象,及參數傳遞。

1 '''例子1'''
2 x = 1
3 def fun(x):
4     x = 2
5     return None
6 
7 fun(x)
8 print(x)

 

其實不打印也可以,我們用pycharm單步調試,看一下在每一行執行中,變量x的值的變化,及其地址的變化(其實這句話應該改成:變量x的指向變化更准確)

Python中id()函數,可以返回對象的地址,id()的官方解釋是:Return the “identity” of an object,既然是identity,肯定是唯一的;官方又說:CPython implementation detail: This is the address of the object in memory。我們暫時把id()返回值看做是對象在內存中的地址。

 

第一步:進入debug,在監視窗口,添加對Id(x),和id(y) 的觀察,藍色高亮,表示下一步將執行,我們看到這時,x,y都沒有分配地址

 

第二步:執行下一步,我們發現變量x,開始分配地址, 1392686144,我們記下這個數。

 

 第三步:進入函數中,執行 x = 2語句,我們發現,x的地址已經變成 1392686176,這就是Python 變量的特性,我們不能理解成把變量x賦值為2,而是“名字為x的標簽指向對象2”,這樣更准確。

 

第四步:返回fun(x)函數,我們發現X的id()值又變回原來的數字,在這個例子中,我們把局部變量和全局變量用同一個標簽指示,當調用函數,進入函數內部執行時,系統會創建堆棧,保留進入函數前的運行環境及數據。進入函數后,有創建了一個同名的標簽x,x = 2,把局部標簽指向局部對象2,這是局部標簽x指向一個新的對象,內存地址肯定變化,當return none,返回函數調用時,堆棧撤銷,局部的對象,變量隨之撤銷,局部標簽x也撤銷,此時x做回自己,變成全局標簽x,依舊指向數字對象1.這就是為什么在函數內部,標簽x指向其他對象后,返回調用,又恢復調用前的內存地址。 

 

 第一個例子中,從標簽x的內存地址變化,幫我們理解Python的變量的行為。

在第二個例子中,我們仍然通過監視標簽的內存地址變化,理解參數傳遞的過程

1 '''例子2'''
2 a = []
3 def fun(a):
4     a.append(1)
5     return None
6 
7 fun(a)
8 print(a)

第一步:執行完函數調用,參數賦值,藍色高亮是下一步將要執行的代碼。我們發現在這一步,發生了參數賦值,創建堆棧,局部標簽x的內存地址與外部標簽a的內存地址相同,說明這一步,完成參數賦值,我們是不是可以把Python的“賦值語句”理解為“標簽指向”這個動作?從這看,這樣理解是可以的。所以“參數賦值”這個動作,可以理解為統一標簽指向。

 

第二步: 當函數返回時,我們發現列表a的地址沒有改變,並且列表中元素1得到保留,沒有因為局部變量撤銷而消失,這回一個典型的通過標簽(引用),在局部過程中改變全局變量的例子。Python標簽的這種特性是不是很像c++中的引用?是不是很像c中的指針? 

 

 總結:Python的變量,我們用標簽來理解,參考c的void*,參考c++中的&,Python的賦值動作,可以理解為“標簽改變指向”的動作。參數傳遞過程,是交換標簽指向的過程


免責聲明!

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



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