我变了,你变不变?
内存相关的小知识
列表(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}] """