• python 可变对象与不可变对象对变量赋值与引用的影响


    前言

    为什么我要用字典类型做测试的载体
    因为在实际开发的过程中,字典是使用频率非常高的一种数据结构,而且不同场景要构造不一样的字典,偶尔踩坑,还是要总结一下经验的,长长记性。

    测试1:列表类型

    # test1
    tt_list = [0 for i in range(3)]
    dd = dict()
    dd.setdefault('a', tt_list)
    dd['a'][0] += 1
    dd.setdefault('b', tt_list)
    dd['b'][1] += 1
    dd.setdefault('c', tt_list)
    dd['c'][2] += 1
    dd
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    期望输出:

    {'a': [1, 0, 0], 'b': [0, 1, 0], 'c': [0, 0, 1]}
    
    • 1

    实际输出:

    {'a': [1, 1, 1], 'b': [1, 1, 1], 'c': [1, 1, 1]}
    
    • 1

    tt_list 为列表推导式赋值的列表,这里测试了在同一个字典对象里的初始化赋值问题,赋值目标为列表类型。
    查看字典里元素值对应的内存地址:

    id(dd['a']), id(dd['b']), id(dd['c'])
    输出:(140408677234432, 140408677234432, 140408677234432)
    
    • 1
    • 2

    明显地,上面用变量去初始化赋值并不是理想的。问题出在用tt_list初始化赋值的时候,实际字典变量指向的是tt_list变量的引用,连续赋值了3次,其实都指向了同一个内存地址,所以任何对字典变量的操作都会影响全局。
    正确示例

    # tt_list = [0 for i in range(3)]
    dd = dict()
    dd.setdefault('a', [0 for i in range(3)])
    dd['a'][0] += 1
    dd.setdefault('b', [0 for i in range(3)])
    dd['b'][1] += 1
    dd.setdefault('c', [0 for i in range(3)])
    dd['c'][2] += 1
    dd
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    输出:

    {'aa': [1, 0, 0], 'bb': [0, 1, 0], 'cc': [0, 0, 1]}
    
    • 1

    查看字典元素值的内存地址:

    id(dd['a']), id(dd['b']), id(dd['c'])
    输出:(140408929043456, 140408929188160, 140408929171072)
    
    • 1
    • 2

    测试2:字符串

    tt_str = ''
    dd = dict()
    dd.setdefault('a', tt_str)
    dd['a'] = 'a'
    dd.setdefault('b', tt_str)
    dd['b'] = 'b'
    dd.setdefault('c', tt_str)
    dd['c'] = 'c'
    dd
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    输出:

    {'a': 'a', 'b': 'b', 'c': 'c'}
    
    • 1

    第二个:

    # tt_str = ''
    dd = dict()
    dd.setdefault('a', '')
    dd['a'] = 'aa'
    dd.setdefault('b', '')
    dd['b'] = 'bb'
    dd.setdefault('c', '')
    dd['c'] = 'cc'
    dd
    输出: {'a': 'aa', 'b': 'bb', 'c': 'cc'}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    查看下内存地址:

    id(dd['a']), id(dd['b']), id(dd['c'])
    输出:(140408404501936, 140408395757296, 140408394948144)
    
    • 1
    • 2

    总结

    实验做到这一步,结论有了,虽然问题看起来是变量赋值和引用的区别,但其实涉及到的知识点是python中的可变对象与不可变对象。

    不可变对象 :int,str,float,tuple – 可理解为C中,值传递
    可变对象 :list,dict – 可理解为C中,指针传递

    还不明白的话,可以继续拿其它数据类型做测试。

  • 相关阅读:
    蓝桥杯(3.1)
    华为云新用户云服务器优惠价格表
    C语言之双向链表
    HTTP 错误 500.19 - Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效——错误代码:0x8007000d
    【软考学习7】数据校验——海明校验码、循环校验码、奇偶校验码
    谷粒学院——前台用户使用系统
    测开 - 自动化测试selenium(WebDriver API) - 细节狂魔
    Node.js最准确历史版本下载
    大数据开发是做什么的?怎样入门?
    告白玫瑰||书信逐字打印效果
  • 原文地址:https://blog.csdn.net/kun_csdn/article/details/126249518