python 深入變數和引用物件
變數和物件
在《learning python》中的一個觀點:變數無型別,物件有型別
在python中,如果要使用一個變數,不需要提前宣告,只需要在用的時候,給這個變數賦值即可。這裡特別強調,只要用一個變數,就要給這個變數賦值。
所以,像這樣是不行的。
>>> x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
反覆提醒:一定要注意看報錯資訊。如果光光地寫一個變數,而沒有賦值,那麼python認為這個變數沒有定義。賦值,不僅僅是給一個非空的值,也可以給一個空值,如下,都是允許的
>>> x = 3
>>> lst = []
>>> word = ""
>>> my_dict = {}
看到上面的圖了吧,從圖中就比較鮮明的表示了變數和物件的關係。所以,嚴格地將,只有放在記憶體空間中的物件(也就是資料)才有型別,而變數是沒有型別的。
同一個變數可以同時指向兩個物件嗎?
>>> x = 4
>>> x = 5
>>> x
5
變數x先指向了物件4,然後指向物件5,自動跟第一個物件4解除關係。再看x,引用的物件就是5了。那麼4呢?一旦沒有變數引用它了,便成了垃圾,python有一個自動的收回機制。
例如:
>>> a = 100 #完成了變數a對記憶體空間中的物件100的引用
然後,又操作了:
>>> a = "hello"
如下圖所示:
原來記憶體中的那個100就做為垃圾被收集了。而且,這個收集過程是python自動完成的,不用我們操心。
那麼,python是怎麼進行垃圾收集的呢?在Quora上也有人問這個問題,我看那個回答很精彩,做個連結:Python (programming language): How does garbage collection in Python work?
is和==的效果
以上過程的原理搞清楚了,下面就可以深入一步了。
>>> l1 = [1,2,3]
>>> l2 = l1
這個操作中,l1和l2兩個變數,引用的是一個物件,都是[1,2,3]。何以見得?如果通過l1來修改[1,2,3],l2引用物件也修改了,那麼就證實這個觀點了。
>>> l1[0] = 99 #把物件變為[99,2,3]
>>> l1 #變了
[99, 2, 3]
>>> l2 #真的變了吔
[99, 2, 3]
再換一個方式:
>>> l1 = [1,2,3]
>>> l2 = [1,2,3]
>>> l1[0] = 99
>>> l1
[99, 2, 3]
>>> l2
[1, 2, 3]
l1和l2貌似指向了同樣的一個物件[1,2,3],其實,在記憶體中,這是兩塊東西,互不相關。只是在內容上一樣。所以,當通過l1修改引用物件的後,l2沒有變化。
進一步還能這麼檢驗:
>>> l1
[1, 2, 3]
>>> l2
[1, 2, 3]
>>> l1 == l2 #兩個相等,是指內容一樣
True
>>> l1 is l2 #is 是比較兩個引用物件在記憶體中的地址是不是一樣
False #前面的檢驗已經說明,這是兩個東東
>>> l3 = l1 #順便看看如果這樣,l3和l1應用同一個物件
>>> l3
[1, 2, 3]
>>> l3 == l1
True
>>> l3 is l1 #is的結果是True
True
某些物件,有copy函式,通過這個函式得到的物件,是一個新的還是引用到同一個物件呢?
實驗:
>>> l1
[1, 2, 3]
>>> l2 = l1[:]
>>> l2
[1, 2, 3]
>>> l1[0] = 22
>>> l1
[22, 2, 3]
>>> l2
[1, 2, 3]
>>> adict = {"name":"hiekay","web":"hiekay.github.io"}
>>> bdict = adict.copy()
>>> bdict
{'web': 'hiekay.github.io', 'name': 'hiekay'}
>>> adict["email"] = "[email protected]"
>>> adict
{'web': 'hiekay.github.io', 'name': 'hiekay', 'email': '[email protected]'}
>>> bdict
{'web': 'hiekay.github.io', 'name': 'hiekay'}
不過,python不總按照前面說的方式,比如小數字的時候
>>> x = 2
>>> y = 2
>>> x is y
True
>>> x = 200000
>>> y = 200000
>>> x is y #什麼道理呀,小數字的時候,就用快取中的.
False
>>> x = 'hello'
>>> y = 'hello'
>>> x is y
True
>>> x = "what is you name?"
>>> y = "what is you name?"
>>> x is y #不光小的數字,短的字串也是
False
賦值是不是簡單地就是等號呢?從上面得出來,=的作用就是讓變數指標指向某個物件。