跟老齊學Python之深入變量和引用對象
在《永遠強大的函數(shù)》那一講中,老齊我已經(jīng)向看官們簡述了一下變量,之后我們就一直在使用變量,每次使用變量,都要有一個操作,就是賦值。本講再次提及這個兩個事情,就是要讓看官對變量和賦值有一個知其然和知其所以然的認識。當然,最后能不能達到此目的,主要看我是不是說的通俗易懂了。如果您沒有明白,就說明我說的還不夠好,可以聯(lián)系我,我再為您效勞。
變量和對象
在《learning python》那本書里面,作者對變量、對象和引用的關(guān)系闡述的非常明了。我這里在很大程度上是受他的啟發(fā)。感謝作者Mark Lutz先生的巨著。
應(yīng)用《learning python》中的一個觀點:變量無類型,對象有類型
在python中,如果要使用一個變量,不需要提前聲明,只需要在用的時候,給這個變量賦值即可。這里特別強調(diào),只要用一個變量,就要給這個變量賦值。
所以,像這樣是不行的。
>>> x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
反復(fù)提醒:一定要注意看報錯信息。如果光光地寫一個變量,而沒有賦值,那么python認為這個變量沒有定義。賦值,不僅僅是給一個非空的值,也可以給一個空值,如下,都是允許的
>>> x = 3
>>> lst = []
>>> word = ""
>>> my_dict = {}
在前面講述中,我提出了一個類比,就是變量通過一根線,連著對象(具體就可能是一個int/list等),這個類比被很多人接受了,算是我老齊的首創(chuàng)呀。那么,如果要用一種嚴格的語言來描述,變量可以理解為一個系統(tǒng)表的元素,它擁有過指向?qū)ο蟮拿臻g。太嚴肅了,不好理解,就理解我那個類比吧。變量就是存在系統(tǒng)中的一個東西,這個東西有一種能力,能夠用一根線與某對象連接,它能夠釣魚。
對象呢?展開想象。在機器的內(nèi)存中,系統(tǒng)分配一個空間,這里面就放著所謂的對象,有時候放數(shù)字,有時候放字符串。如果放數(shù)字,就是int類型,如果放字符串,就是str類型。
接下來的事情,就是前面說的變量用自己所擁有的能力,把對象和自己連接起來(指針連接對象空間),這就是引用。引用完成,就實現(xiàn)了賦值。
看到上面的圖了吧,從圖中就比較鮮明的表示了變量和對象的關(guān)系。所以,嚴格地將,只有放在內(nèi)存空間中的對象(也就是數(shù)據(jù))才有類型,而變量是沒有類型的。這么說如果還沒有徹底明白,就再打一個比喻:變量就好比釣魚的人,湖水里就好像內(nèi)存,里面有好多魚,有各種各樣的魚,它們就是對象。釣魚的人(變量)的任務(wù)就是用某種方式(魚兒引誘)把自己和魚通過魚線連接起來。那么,魚是有類型的,有鰱魚、鯽魚、帶魚(帶魚也跑到湖水了了,難道是淡水帶魚?呵呵,就這么扯淡吧,別較真),釣魚的人(變量)沒有這種類型,他釣到不同類型的魚。
這個比喻太爛了。湊合著理解吧。看官有好的比喻,別忘記分享。
同一個變量可以同時指向兩個對象嗎?絕對不能腳踩兩只船。如果這樣呢?
>>> x = 4
>>> x = 5
>>> x
5
變量x先指向了對象4,然后指向?qū)ο?,當后者放生的時候,自動跟第一個對象4接觸關(guān)系。再看x,引用的對象就是5了。那么4呢?一旦沒有變量引用它了,它就變成了孤魂野鬼。python是很吝嗇的,它絕對不允許在內(nèi)存中存在孤魂野鬼。凡是這些東西都被看做垃圾,而對垃圾,python有一個自動的收回機制。
在網(wǎng)上找了一個圖示說明,很好,引用過來(來源:http://www.linuxidc.com/Linux/2012-09/69523.htm)
>>> a = 100 #完成了變量a對內(nèi)存空間中的對象100的引用
如下圖所示:
然后,又操作了:
>>> a = "hello"
如下圖所示:
原來內(nèi)存中的那個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 #把對象變?yōu)閇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],其實,在內(nèi)存中,這是兩塊東西,互不相關(guān)。只是在內(nèi)容上一樣。就好像是水里長的一樣的兩條魚,兩個人都釣到了,當不是同一條。所以,當通過l1修改引用對象的后,l2沒有變化。
進一步還能這么檢驗:
>>> l1
[1, 2, 3]
>>> l2
[1, 2, 3]
>>> l1 == l2 #兩個相等,是指內(nèi)容一樣
True
>>> l1 is l2 #is 是比較兩個引用對象在內(nèi)存中的地址是不是一樣
False #前面的檢驗已經(jīng)說明,這是兩個東東
>>> l3 = l1 #順便看看如果這樣,l3和l1應(yīng)用同一個對象
>>> l3
[1, 2, 3]
>>> l3 == l1
True
>>> l3 is l1 #is的結(jié)果是True
True
某些對象,有copy函數(shù),通過這個函數(shù)得到的對象,是一個新的還是引用到同一個對象呢?看官也可以做一下類似上面的實驗,就曉得了。比如:
>>> l1
[1, 2, 3]
>>> l2 = l1[:]
>>> l2
[1, 2, 3]
>>> l1[0] = 22
>>> l1
[22, 2, 3]
>>> l2
[1, 2, 3]
>>> adict = {"name":"qiwsir","web":"qiwsir.github.io"}
>>> bdict = adict.copy()
>>> bdict
{'web': 'qiwsir.github.io', 'name': 'qiwsir'}
>>> adict["email"] = "qiwsir@gmail.com"
>>> adict
{'web': 'qiwsir.github.io', 'name': 'qiwsir', 'email': 'qiwsir@gmail.com'}
>>> bdict
{'web': 'qiwsir.github.io', 'name': 'qiwsir'}
不過,看官還有小心有點,python不總按照前面說的方式出牌,比如小數(shù)字的時候
>>> x = 2
>>> y = 2
>>> x is y
True
>>> x = 200000
>>> y = 200000
>>> x is y #什么道理呀,小數(shù)字的時候,就用緩存中的.
False
>>> x = 'hello'
>>> y = 'hello'
>>> x is y
True
>>> x = "what is you name?"
>>> y = "what is you name?"
>>> x is y #不光小的數(shù)字,短的字符串也是
False
賦值是不是簡單地就是等號呢?從上面得出來,=的作用就是讓變量指針指向某個對象。不過,還可以再深入一些。走著瞧吧。
- Python為何不能用可變對象作為默認參數(shù)的值
- Python面向?qū)ο蟪绦蛟O(shè)計類變量與成員變量、類方法與成員方法用法分析
- Python面向?qū)ο蟪绦蛟O(shè)計中類的定義、實例化、封裝及私有變量/方法詳解
- 基于Python對象引用、可變性和垃圾回收詳解
- 淺談Python中的可變對象和不可變對象
- python編程進階之類和對象用法實例分析
- Python面向?qū)ο笾蓄悾╟lass)的簡單理解與用法分析
- Python轉(zhuǎn)換itertools.chain對象為數(shù)組的方法
- Python 面向?qū)ο笾恈lass和對象基本用法示例
- Python可變對象與不可變對象原理解析
相關(guān)文章
Python中的sorted函數(shù)應(yīng)用及文件操作詳解
這篇文章主要介紹了Python中的sorted函數(shù)應(yīng)用及文件操作詳解,python只能將字符串寫入到文本文件,要將數(shù)值數(shù)據(jù)存儲到文本本件中,必須先試用函數(shù)str()將其轉(zhuǎn)換為字符串格式,需要的朋友可以參考下2023-12-12python爬蟲爬取監(jiān)控教務(wù)系統(tǒng)的思路詳解
這篇文章主要介紹了python爬蟲監(jiān)控教務(wù)系統(tǒng),主要實現(xiàn)思路是對已有的成績進行處理,變?yōu)閘ist集合,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2020-01-01python 將md5轉(zhuǎn)為16字節(jié)的方法
今天小編就為大家分享一篇python 將md5轉(zhuǎn)為16字節(jié)的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05python_array[0][0]與array[0,0]的區(qū)別詳解
今天小編就為大家分享一篇python_array[0][0]與array[0,0]的區(qū)別詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02