V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
meteordragon
V2EX  ›  Python

小白发现一个 dict 的奇怪现象,请问有什么办法可以避免

  •  
  •   meteordragon · 2021-05-09 21:07:53 +08:00 · 3295 次点击
    这是一个创建于 1054 天前的主题,其中的信息可能已经有所发展或是发生改变。
    dd={"a":"1","b":"2"}
    cc=dd
    cc["c"]="3"
    print(dd)
    print(cc)

    运行结果是
    {'a': '1', 'b': '2', 'c': '3'}
    {'a': '1', 'b': '2', 'c': '3'}

    改变 cc 的值同时改变 dd 的值
    list 变量有同样的问题
    但是我他赋值给另一个变量的目的就是不改变它的值啊。请问有什么办法避免这个问题吗?还是说是我的 python 环境有问题呢?
    21 条回复    2021-07-17 08:31:27 +08:00
    Jakarta
        1
    Jakarta  
       2021-05-09 21:09:16 +08:00
    python 深拷贝 浅拷贝
    mcoo1997
        2
    mcoo1997  
       2021-05-09 21:11:43 +08:00 via Android
    import copy
    copy.deepcopy(cc)
    jmc891205
        3
    jmc891205  
       2021-05-09 21:14:04 +08:00
    cc = dict(dd)
    di94sh
        4
    di94sh  
       2021-05-09 21:15:59 +08:00 via iPhone   ❤️ 1
    python 基础知识 可变对象与不可变对象
    mostkia
        5
    mostkia  
       2021-05-09 21:18:04 +08:00
    一般的赋值操作,只是拷贝了目标对象的一个内存地址的引用,类似安装的程序,你只拷贝了一个快捷方式,程序被删了或改变了,所有的快捷方式都会跟着失效变动,js 语言也有这类问题,尝试用深拷贝。
    ch2
        6
    ch2  
       2021-05-09 22:06:21 +08:00
    c#+js+python 都是这样
    xiri
        7
    xiri  
       2021-05-09 22:16:50 +08:00   ❤️ 1
    改成 cc=dd.copy() 就行了,这是很基础的问题,深浅拷贝
    meteordragon
        8
    meteordragon  
    OP
       2021-05-09 22:20:55 +08:00
    感谢各位前辈,之前真没注意过这个问题
    jotpot
        9
    jotpot  
       2021-05-09 23:00:22 +08:00
    确实是小白。所有的编程语言都有引用和 clone 的问题
    nightwitch
        10
    nightwitch  
       2021-05-09 23:02:17 +08:00
    引用语义和值语义的差别,不同语言有不同的倾向。
    muzuiget
        11
    muzuiget  
       2021-05-10 01:17:36 +08:00
    引用问题,建议把基础部分重看一次。
    littlewey
        12
    littlewey  
       2021-05-10 01:48:17 +08:00 via iPhone
    看一下
    id(cc)
    id(dd)
    wd
        13
    wd  
       2021-05-10 05:44:01 +08:00 via iPhone
    感觉隔一段时间就有人来这里说说这个问题...
    HashV2
        14
    HashV2  
       2021-05-10 09:06:58 +08:00
    我一周看到三四次这个问题了,在不同的语言节点。。
    no1xsyzy
        15
    no1xsyzy  
       2021-05-10 09:22:49 +08:00
    应该不算深浅拷贝问题,而是拷贝与引用的问题。

    但我觉得你的需求更大可能应该写成
    cc = {**dd, "c":"3"}
    展开式浅拷贝同时进行修改是非常好用的糖

    @jotpot 略暴言。C 语言没有引用与 clone 的问题,都是 clone,只不过 clone 的可能是指针(地址)。你若是非要传参传 struct 而不是 struct* 也给你全量拷贝了(通常没人这么用罢了)。Pascal 类似。
    函数式语言也不会遇到这个问题,因为全都不可变了,就没引用和 clone 的差异了。
    Kilerd
        16
    Kilerd  
       2021-05-10 09:29:13 +08:00
    这是 python 有史以来的 bug,建议换一门语言以避免同样的 bug
    RRRoger
        17
    RRRoger  
       2021-05-10 09:42:10 +08:00
    百度谷歌随便一搜就有解决方案
    charlie21
        18
    charlie21  
       2021-05-10 15:59:46 +08:00 via iPhone
    “(用等号)赋值给另一个变量的目的就是不改变它的值”
    这个目的没错,但只限于值类型的变量。
    参考 v2ex.com/t/774968 24 楼 PHP 语言
    ddzzhen
        19
    ddzzhen  
       2021-05-10 21:08:17 +08:00 via Android
    赋值操作是链接,占用内存不增加
    xiaoxinshiwo
        20
    xiaoxinshiwo  
       2021-05-11 16:05:33 +08:00
    [捂眼睛]
    IgniteWhite
        21
    IgniteWhite  
       2021-07-17 08:31:27 +08:00
    @xiri cc=dd.copy() 也是浅拷贝。
    @jmc891205 cc=dict(dd) 也是浅拷贝。
    只有 @mcoo1997 在二楼使用 copy.deepcopy()是深拷贝。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5369 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 08:02 · PVG 16:02 · LAX 01:02 · JFK 04:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.