可變型別變數(列表、字典等)定為函式預設值時的陷阱
可變型別變數在函式預設值中的一坑,以後大家記得繞著走,話不多說,上程式碼!
可變型別變數列表測試:
def abc(a=[]): a.append(123) print(a) abc() abc()
此時大家可能覺得應該輸出如下內容:
[123] [123]
其實不然,實際情況如下:
[123] [123, 123]
那換另一個可變型別變數字典試下呢?
import random def abc(a={}): a[random.randint(1, 5)] = '123' print(a) abc() abc()
此時大家可能覺得應該輸出如下內容:
{隨機值: '123'} {隨機值: '123'}
其實不然,實際情況如下:
{2: '123'} {2: '123', 3: '123'}
那麼換成不可變型別變數會是怎樣的呢?那麼拿字串來舉例:
def abc(a=''): a = a + '1' print(a) abc() abc()
按照上面的慣性大家可能會以為輸出結果為下面這樣:
其實不然,實際情況如下:
總結:
1、表象:在python中可變型別變數作為預設值賦給函式時,多次呼叫該函式實際只初始化一次,這看起來好像是個bug。
2、本質:在python中對不可變型別(比如字串)進行修改後其實不是對原本的值進行了更改(不可變型別之所以叫不可變型別就是值是固定的,不可修改),而是又開闢了一塊新記憶體來新建立了一個值,然後再將變數指向這個新值的記憶體地址
def abc(a=[]):===>假設此處空列表位於記憶體0x00001111 a.append(123)===>將記憶體0x00001111的值增加了一個“123” print(a) abc() abc() ====>第二次呼叫時a的預設值其實還是原來的空列表記憶體處的值,即0x00001111,只不過此時該值增加了一個“123” def abc(a=''):===>假設此處空列表位於記憶體0x00001111 a = a + '1'===>由於字串為不可變型別,故此處其實是將a指向了另外一個記憶體空間,假設為0x00002222,而在0x00002222處存放了一個"1" print(a) abc() abc() ====>第二次呼叫時a的預設值其實還是原來的空字串記憶體處的值,即0x00001111,由於上一次變化是將a指向了另外一個值,所以此處的值還為空字串
如需要可變型別變數作為預設值時可以採用如下方法:
def abc(a=None): a = [] a.append(123) print(a) abc() abc()
輸出結果為:
[123] [123]