1. 程式人生 > >2 -1 變數

2 -1 變數

變數的建立與id

例1:name = 'oldboy'

首先,當我們定義了一個變數name = ‘oldboy’的時候,在記憶體中其實是做了這樣一件事:

程式開闢了一塊記憶體空間,將‘oldboy’儲存進去,再讓變數名name指向‘oldboy’所在的記憶體地址。如下圖所示:

例2:兩個變數名一個值

提問:當我執行下面這段程式碼的時候,程式是怎麼處理的呢?

1 name1 = 'oldboy'
2 name2 = 'oldboy'

我們猜想會有兩種可能:

第一種情況:程式分別在記憶體中開闢了兩塊兒空間來儲存‘oldboy’這個值,並且讓name1和name2指向這兩個值。如下左圖

第二種情況:由於兩個值內容一致,所以程式只開闢一塊兒空間儲存‘oldboy’,並讓name1和name2只想著個值。如下右圖

提問:大家來猜測一下會是哪種情況?

其實上面的兩種猜想都是對的。正常情況下字串在記憶體裡就是如我們猜想的第一種情況一樣,每一次建立一個變數都會在記憶體中申請一塊兒空間。

但是,python認為一些“看起來像python識別符號的字元”和小整數字在開發中是常用的,因此出於節省記憶體的角度思考,對於這部分字串和數字做出了優化[-5,257),

python直譯器會由於要定義的新變數內容與之前定義過的變數內容相同而不讓這部分內容佔用新的記憶體空間。

我們如何證明我們的想法呢?

 

python為我們提供了一個id()方法,可以檢視一個變數的記憶體地址。

name1 = 'oldboy'
name2 = 'oldboy'
name1_id = id(name1)
name2_id = id(name2)
print(name1_id,name2_id)
32231696 32231696

Process finished with exit code 0

執行完這段程式碼就基本驗證了我們的思想,由於‘oldboy’是一個簡單的字串,因此python直譯器做了優化,記憶體裡只有一個‘oldboy’,name1和name2都指向同一塊兒記憶體地址。

 

如果是長字串呢?就米有優化機制啦!

a = "this is a very long sentence"
b = "this is a very long sentence"
print(id(a),id(b))
6804784 6804784

Process finished with exit code 0

 

對於[-5,257)範圍內的數字也有優化機制:

a = 257
b = 257
print(id(a),id(b))
34721552 34721552

a1 = -5
b1 = -5
print(id(a1),id(b1))
1607822160 1607822160

但是超過這個範圍可就不太行了:

a = -6
b = -6
print(id(a),id(b))
34962320 34962384


#理論到257,兩邊的記憶體地址就會不一樣,但是現在259都是一樣的,尷尬了
a1 = 259
b1 = 259
print(id(a1),id(b1))
1683152 1683152

例3:一個變數名2個值

 

提問:如果像下面這樣寫自己的程式碼,最終列印name會得到什麼結果?

name = 'oldboy'
name = 'alex'
print(name)

 

我想大家的答案是一致的,name此時應該是‘alex’,當我們在程式中對變數進行重複賦值時,就是對一個變數進行修改.

程式碼解讀:

程式先申請了一塊記憶體空間來儲存‘oldboy’,讓name變數名指向這塊記憶體空間

讀到name=‘alex’之後又申請了另一塊記憶體空間來儲存‘alex’,並讓原本指向‘oldboy’記憶體的連結斷開,讓name再指向‘alex’。

如下圖所示:

例4:變數的賦值與修改

 

提問:如果像下面這樣寫自己的程式碼,最終列印name1和name2會分別得到什麼結果?

  

name1 = 'oldboy'
name2 = name1
name1 = 'alex'
print(name1,name2)

 

這裡大家就會產生一些爭論了,先執行一下給大家看。

name1 = 'oldboy'
name2 = name1
name1 = 'alex'
print(name1,name2)

#執行結果
alex oldboy

Process finished with exit code 0

要想知道上面問題的結果是為什麼,首先要了解在記憶體中兩個變數的儲存情況

從上面的示意圖中我們可以知道,當執行name2=name1這句話的時候,事實上是讓name2指向了‘oldboy’所在的記憶體地址。

修改name1的值,相當於斷開了name1到‘oldboy’的連結,重新建立name1和‘alex’之間的連結。在這個過程中,始終沒有影響到name2和‘oldboy‘之間的關係,因此name2還是‘oldboy’,而name1變成了‘alex’。

身份運算