在函數以外建立的變量屬於main,又被稱爲全局變量。它們能夠在main中的任意函數中訪問,與局部變量在函數結束時消失不一樣,全局變量能夠在不一樣函數的調用之間持久存在。全局變量經常用做標誌(Flags)。標誌是一種布爾型變量,能夠標誌一個條件是否爲真。html
verbose = True def example(): if verbose: print('你好,今每天氣很好!') else: print('你好')
若是在函數裏嘗試給全局變量賦值,必須先用global關鍵字進行聲明,不然函數會建立一個同名局部變量而不是使用全局變量。python
verbose = True def example(): global verbose verbose = False print('你好')
在Python中,string、tuple和number是不可變對象,而list、dict等是可變對象。shell
先來看一段代碼:app
b = [1, 2, 3] a = b print(a is b) # True b.append(4) print(a) # [1, 2, 3, 4]
a is b
返回True,說明這python內部a與b是相同的,變量a與變量b都指向同一個對象。此時稱a和b爲這個對象的別名。當對象的值發生改變時,a和b天然也會隨之改變。若是a、b只是值相等而不指向同一個對象,咱們稱a與b是相等的。相同一定相等,相等不必定相同。函數
a = [1, 2, 3] b = [1, 2, 3] print(a is b) # False
咱們平時說的【變量】其實只是標籤,是對內存中對象的引用。賦值操做只是給變量一個指向對象的引用性能
寫代碼的時候經常用is和==來比較兩個對象是否相等,可是它們有什麼不一樣呢?參考下面的例子:優化
a = 1 b = 1 a == b # True a is b # True a = 888 b = 888 a == b # True a is b # False a = 'hello' b = 'hello' a is b # True a == b # True a = 'hello world' b = 'hello world' a == b # True a is b # False
is和==的結果不一樣!不是說好的都是比較兩個對象是否相等嗎?怎麼到這裏變了樣了?不急,先介紹一下python內置的一個函數:id(),這個函數會打印參數的內存地址,讓咱們來試試:spa
a = 888 b = 888 id(a) # 1939743592336 id(b) # 1939745557808 a = 'hello world' b = 'hello world' id(a) # 1939745897200 id(b) # 1939745912624
能夠看到,儘管a、b的值是相同的,可是其內存地址卻不一樣。那麼答案就很顯然了,is比較的是兩個對象的內存地址是否相等,==比較的是兩個對象的值是否相等。這樣就能解釋爲何is和==的結果不一樣了。code
But wait,那麼爲何當a、b的值爲1和'hello'時,is與==的結果是同樣的呢?這就要說到python的小整數池和垃圾回收機制了。python爲了讓運行速度快些,在內存中專門開闢了一塊區域放置-5到256,全部表明-5到256的對象都會指向這個區域。htm
相似的,字符串類型做爲Python中最經常使用的數據類型之一,Python解釋器爲了提升字符串使用的效率和使用性能,作了不少優化。例如:Python解釋器中使用了intern(字符串駐留)的技術來提升字符串效率,什麼是intern機制?即值一樣的字符串對象僅僅會保存一份,放在一個字符串儲蓄池中,是共用的,固然,確定不能改變,這也決定了字符串必須是不可變對象。
同時,若是字符串中有空格,默認不啓用intern機制。對字符串儲蓄池中的字符串使用is和==比較會獲得相同的結果。:
a = 1 b = 1 id(a) # 1963327952 id(b) # 1963327952 a = 'hello' b = 'hello' id(a) # 1939745887600 id(b) # 1939745887600
注意:在shell中,僅有如下劃線、數字、字母組成的字符串會被intern。而pycharm中只要是同一個字符串不超過20個字符都被加入到池中
python函數參數傳遞是引用傳遞:
def test(n): print(id(n)) k = "string" id(k) # 2305161642256 test(k) # 2305161642256
經常使用的拷貝方式有:
淺拷貝屬於「新瓶裝舊酒」,即生成了一個新的變量,而變量所指向的對象和原來的是同樣的:
l = ["hello", [2, 3, 4]] id(l) # 3048239386824 [id(i) for i in l] # [1524761040, 1524761072] k = l.copy() id(k) # 3048239387080,地址不一樣,k是另外一個變量 [id(i) for i in k] # [1524761040, 1524761072],地址相同,指向同一個變量
深拷貝屬於「新瓶裝新酒」,即生成了一個新變量,指向和原對象相等的新對象(不可變對象除外):
import copy l = ["hello world", [2, 3, 4]] id(l) # 3048239386824 [id(i) for i in l] # [3048239385040, 3048239387080] k = copy.deepcopy(l) id(k) # 3048240927048,地址不一樣,k是另外一個變量 [id(i) for i in k] # [3048239385040, 3048240927304],字符串是不可變對象,因此仍指向原地址,對於list