我变了,你变不变?

内存相关的小知识

  1. 列表(list)/字典(dict)/集合(set)

    • 情况一:

      SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
      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不改变
      • 重新赋值不修改内存中的元素,只改变值的指向
  2. 字符串(str)/元组(tuple)

    • 只有情况二,只能重新赋值,不能修改
  3. 总结

    • 在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小数据池除外
  4. 练习题

    #看代码写结果并解释原因
    #练习题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}]
    """
    
扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄