我變了,你變不變? 記憶體相關的小知識 1. 列表(list)/字典(dict)/集合(set) 情況一: 修改記憶體中的元素,所有指向那個記憶體的值都會改變 情況二: 重新賦值不修改記憶體中的元素,只改變值的指向 2. 字元串(str)/元組(tuple) 只有情況二,只能重新賦值,不能修改 3. 總結 ...
我變了,你變不變?
記憶體相關的小知識
列表(list)/字典(dict)/集合(set)
情況一:
v1 = [1,2,3] v2 = v1 v1.append(4) #增加 print(v2) #[1,2,3,4] #在v1裡面修改(增加/刪除),v2也跟著改變
- 修改記憶體中的元素,所有指向那個記憶體的值都會改變
情況二:
v1 = [1,2,3] v2 = v1 v1 = [3,4,5] #重新賦值 print(v2) #[1,2,3] #重新賦值v1,v2不改變
- 重新賦值不修改記憶體中的元素,只改變值的指向
字元串(str)/元組(tuple)
- 只有情況二,只能重新賦值,不能修改
總結
在python中,為了提高性能,值若是以下情況(python小數據池),就不重新開闢記憶體
- 常用數字:-5~256
- 簡單字元串:如'alex',除去 'alex' * 3(數字大於1) 這種情況
== 比較的是值是否相等,is 比較的是記憶體地址是否相等
#例1: v1 = [1,2] v2 = [1,2] v1 == v2 #True v1 is v2 #False #例2: v1 = [1,2] v2 = v1 v1 == v2 #True v1 is v2 #True
- 註:python小數據池除外
練習題
#看代碼寫結果並解釋原因 #練習題1: v1 = {'k1':'v1','k2':[1,2,3]} v2 = v1 v1['k1'] = 'wupeiqi' print(v2) """ 結果: {'k1':'wupeiqi','k2':[1,2,3]} 原因: 因為v1和v2指向的記憶體地址是同一個, 修改v1裡面的元素,相當於修改的是記憶體地址中的元素, 所以v2也會跟著改變,因此輸出的v2也改變了 """ #練習題2: v1 = '人生苦短,我用Python' v2 = [1,2,3,4,v1] v1 = "人生苦短,用毛線Python" print(v2) """ 結果: [1,2,3,4,'人生苦短,我用Python'] 原因: 一開始,v2中的v1和v1指向的記憶體地址是同一個, 給v1重新賦值,只改變v1的指向,相當於v1指向了一個新的記憶體地址, 而v2中v1的還是指向原來的那個記憶體地址,所以輸出的v2不改變 """ #練習題3: info = [1,2,3] userinfo = {'account':info, 'num':info, 'money':info} info.append(9) print(userinfo) info = "題怎麼這麼多" print(userinfo) """ 結果: {'account':[1,2,3,9], 'num':[1,2,3,9], 'money':[1,2,3,9]} #第一個userinfo {'account':[1,2,3,9], 'num':[1,2,3,9], 'money':[1,2,3,9]} #第二個userinfo 原因: 一開始,userinfo中的info和info指向的記憶體地址是同一個, 先修改info裡面的元素,相當於修改的是記憶體地址中的元素, 所以userinfo中info也會跟著改變,因此輸出的第一個userinfo也改變了, 再給info重新賦值,只改變info的指向,相當於info指向了一個新的記憶體地址, 而userinfo中info的還是指向原來的那個記憶體地址, 所以輸出的第二個userinfo不再改變,還是第一個userinfo的值 """ #練習題4: info = [1,2,3] userinfo = [info,info,info,info,info] info[0] = '不僅多,還特麽難呢' print(info,userinfo) """ 結果: ['不僅多,還特麽難呢',2,3] #info [['不僅多,還特麽難呢',2,3],['不僅多,還特麽難呢',2,3],['不僅多,還特麽難呢',2,3], ['不僅多,還特麽難呢',2,3],['不僅多,還特麽難呢',2,3]] #userinfo 原因: userinfo中的info和info指向的記憶體地址是同一個, 修改info裡面的元素,相當於修改的是記憶體地址中的元素, 所以userinfo中info也會跟著改變,因此輸出的info和userinfo都改變了 """ #練習題5: info = [1,2,3] userinfo = [info,info,info,info,info] userinfo[2][0] = '閉嘴' print(info,userinfo) """ 結果: ['閉嘴',2,3] #info [['閉嘴',2,3],['閉嘴',2,3],['閉嘴',2,3],['閉嘴',2,3],['閉嘴',2,3]] #userinfo 原因: userinfo中的info和info指向的記憶體地址是同一個, 修改userinfo中的info裡面的元素,相當於修改的是記憶體地址中的元素, 所以所有info都會跟著改變,因此輸出的info和userinfo都改變了 """ #練習題6: info = [1, 2, 3] user_list = [] for item in range(10): user_list.append(info) info[1] = "是誰說Python好學的?" print(user_list) """ 結果: [[1, "是誰說Python好學的?", 3],[1, "是誰說Python好學的?", 3], [1, "是誰說Python好學的?", 3],[1, "是誰說Python好學的?", 3], [1, "是誰說Python好學的?", 3],[1, "是誰說Python好學的?", 3], [1, "是誰說Python好學的?", 3],[1, "是誰說Python好學的?", 3], [1, "是誰說Python好學的?", 3],[1, "是誰說Python好學的?", 3]] 原因: for迴圈讓user_list迴圈追加info了10次,此時相當於 user_list = [info,info,info,info,info,info,info,info,info,info], userinfo中的info和info指向的記憶體地址是同一個, 修改info裡面的元素,相當於修改的是記憶體地址中的元素, 所以userinfo中info也會跟著改變,因此輸出的userinfo改變了 """ #練習題7: data = {} for item in range(10): data['user'] = item print(data) """ 結果: {'user':9} 原因: 對於for迴圈,第一次迴圈時給data添加了'user':0這個元素, 後面的每一次迴圈,都在修改'user'這個鍵所對應的值, 最後一次迴圈將值修改為9,所以輸出結果為{'user':9} """ #練習題8: data_list = [] data = {} for item in range(10): data['user'] = item data_list.append(data) print(data_list) """ 結果: [{'user':9},{'user':9},{'user':9},{'user':9},{'user':9}, {'user':9},{'user':9},{'user':9},{'user':9},{'user':9}] 原因: 對於for迴圈, 第一次迴圈時,給data添加了'user':0這個元素,即data = {'user':0}, 再將date追加到data_list中,此時data_list = [date],即data_list = [{'user':0}], 此時data_list中的date和data指向的記憶體地址是同一個, 第二次迴圈時,修改了date中'user'對應的值,此時data = {'user':1}, 再將date追加到data_list中,此時data_list = [date,date], 因為data_list中的date和data指向的記憶體地址是同一個, 修改date裡面的元素,相當於修改的是記憶體地址中的元素, 所以data_list中date也會跟著改變,因此data_list中第一個date的值也改變了, 即data_list = [{'user':1},{'user':1}], 同理,每迴圈一次,date就修改一次,data_list中所有date都跟著改變, 最後一次迴圈時,將'user'對應的值修改為9,所以data = {'user':9}, 此時,data_list中所有date都改變了,都變為{'user':9}, 即輸出的data_list = [{'user':9},{'user':9},{'user':9},{'user':9},{'user':9}, {'user':9},{'user':9},{'user':9},{'user':9},{'user':9}] """ #練習題9: data_list = [] for item in range(10): data = {} data['user'] = item data_list.append(data) print(data_list) """ 結果: [{'user':0},{'user':1},{'user':2},{'user':3},{'user':4}, {'user':5},{'user':6},{'user':7},{'user':8},{'user':9}] 原因: 第一次迴圈時,給data添加了'user':0這個元素,即data = {'user':0}, 再將date追加到data_list中,此時data_list = [date],即data_list = [{'user':0}], 此時data_list中的date和data指向的記憶體地址是同一個, 第二次迴圈時,給date重新賦值,只改變date的指向,相當於date指向了一個新的記憶體地址, 再給data添加了'user':1這個元素,即data = {'user':1}, 再將date追加到data_list中,此時data_list = [date,date], 此時data_list中的第一個date還是指向的原來那個記憶體地址,所以第一個date不再改變, 此時data_list中的第二個date和data指向的記憶體地址都是新的記憶體地址,是同一個, 同理,依次迴圈,每迴圈一次,就給date重新賦值一次, 就相當於每次迴圈都重新開闢了一個新的地址給date, 而data_list中前面date還是分別指向它們原來的記憶體地址,所以都不再改變, 最後一次迴圈時,data = {'user':9},data_list中前面date都不再改變了, 只把新的date再追加進去,即輸出的data_list = [{'user':0},{'user':1},{'user':2},{'user':3},{'user':4}, {'user':5},{'user':6},{'user':7},{'user':8},{'user':9}] """