Python 變量,是容器還是標(biāo)簽?
大家好,歡迎來(lái)到 Crossin的編程教室 !
上一次,我們聊了點(diǎn)關(guān)于 Python 中變量的基礎(chǔ)知識(shí)點(diǎn)。今天繼續(xù)這個(gè)話題聊下去。
1. 變量的賦值
之前說(shuō)到,Python 中的「賦值」操作符就是一個(gè)等號(hào)(=)。通過(guò)賦值操作可以創(chuàng)建一個(gè)變量,也可以修改一個(gè)變量的已有值。
那有人就要說(shuō)了:
為什么 a = 1 可以賦值,1 = a 就會(huì)報(bào)錯(cuò)?這不都是一個(gè)等式嗎?
這是因?yàn)?Python 的賦值操作符(=)并不等同于數(shù)學(xué)中的等式。數(shù)學(xué)中等式滿足交換律,左右兩邊互換沒(méi)有問(wèn)題。但編程中的賦值是有方向的,是把等號(hào)右邊的結(jié)果賦值給左邊的變量。
理解了賦值的方向性,很多語(yǔ)法就好理解了:
就是把右邊的數(shù)值1賦值給左邊的變量a,這沒(méi)毛病。
右邊是變量a的值這沒(méi)問(wèn)題,但左邊被賦值的是一個(gè)數(shù)值,這就不行了,所以報(bào)錯(cuò)。?
因?yàn)槭前延疫叺摹敖Y(jié)果”賦值給左邊的變量,所以右邊不僅可以是一個(gè)固定值,也可以是個(gè)計(jì)算式:
這個(gè)計(jì)算式里也可以含有變量:
甚至可以帶有函數(shù),只要保證計(jì)算式本身是可執(zhí)行的就行:
于是,被賦值的變量本身也可以作為右邊計(jì)算式的一部分:
這個(gè)式子以數(shù)學(xué)的眼光來(lái)看顯然是不成立,但在編程中非常常見(jiàn),作用就是把變量 a 的值增加 1。
它還有個(gè)簡(jiǎn)化寫(xiě)法:
類似還有 -=、*=、/=、%=、//= 等等。
如果你學(xué)過(guò) C++,應(yīng)該知道這種變量自增 1 的語(yǔ)句還有種更簡(jiǎn)化的寫(xiě)法:
但不好意思,這里是 Python,不能這么寫(xiě)。?
至于數(shù)學(xué)中的等式,Python 更接近的比較運(yùn)算符(==),比如:
用來(lái)判斷(==)左右兩邊的計(jì)算結(jié)果是否相等,結(jié)果是 True 或者 False。這個(gè)我們下回再來(lái)細(xì)說(shuō)。
2. Python 變量不是一個(gè)「容器」
接下來(lái)講的這點(diǎn)有一點(diǎn)點(diǎn)進(jìn)階。
很多人在了解的變量的使用之后,可能會(huì)把變量想象一個(gè)裝數(shù)據(jù)的「容器」,就好比一個(gè)杯子,賦值就是往里面倒飲料,重新賦值就是倒上其他的飲料。
這種理解在 C++ 這樣的語(yǔ)言里是沒(méi)有問(wèn)題的。也正因?yàn)槿绱?,C++ 才需要在使用前「定義」變量,確定類型,程序也會(huì)分配好對(duì)應(yīng)的內(nèi)存空間。
但可惜,在 Python 里這個(gè)理解是錯(cuò)誤的。?
Python 里的變量,與其說(shuō)是裝數(shù)據(jù)的容器,倒不如說(shuō)是貼在數(shù)據(jù)上的標(biāo)簽。
變量并不占用空間,占用空間的是數(shù)據(jù)本身。當(dāng)你重新賦值時(shí),就相當(dāng)于撕下這個(gè)標(biāo)簽,貼紙另一個(gè)數(shù)據(jù)上。
Python 中所有東西都是對(duì)象,包括函數(shù)、類、模塊,甚至是字符串’hello’,數(shù)字1、2、3,都是對(duì)象。
用個(gè)例子來(lái)說(shuō)明:
在這個(gè)代碼里,a 和 c 其實(shí)指向的是同一個(gè)對(duì)象—整數(shù) 1。給 a 賦值為 b 之后,a 就變成了指向 2 的標(biāo)簽,但 1 和 c 都不會(huì)受影響。
示意圖:

更有說(shuō)服力一點(diǎn)的驗(yàn)證:
輸出:
id() 可以認(rèn)為是獲取一個(gè)對(duì)象的地址??梢钥闯?,a 和 c 開(kāi)始其實(shí)是同一個(gè)地址,而后來(lái)賦值之后,a 又和 b 是同一個(gè)地址。
每次給變量重新賦值,它就指向了新的地址,與原來(lái)的地址無(wú)關(guān)了。
對(duì)于 Python 的變量賦值,你還要什么想了解的內(nèi)容?歡迎在留言區(qū)討論。
