V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
hackpro
V2EX  ›  问与答

Python Name Bind 问题

  •  
  •   hackpro · 2018-08-30 10:02:16 +08:00 · 805 次点击
    这是一个创建于 2079 天前的主题,其中的信息可能已经有所发展或是发生改变。
    Techs = ['MIT', 'Caltech'] 
    Ivys = ['Harvard', 'Yale', 'Brown']
    Univs = [Techs, Ivys]
    Univs1 = [['MIT', 'Caltech'], ['Harvard', 'Yale', 'Brown']]
    print('Univs =', Univs)
    print('Univs1 =', Univs1)
    print('id(Univs) =', id(Univs))
    print('id(Univs1) =', id(Univs1))
    

    但实际运行效果如下

    按照我自己的理解,如果 name bind 能够找到一个完全相同的 object,就不会重新创建一份 copy

    但实际运行的结果和之前的总结似乎大相径庭

    类似的问题还出现在 pass value by value/reference,网上也搜了一下这方面的 blog,但没找到说得特别清楚的

    大佬们有推荐的 tutorial 链接吗 Python 语言何时创建新的 Object 有什么原则吗?

    5 条回复    2018-08-30 11:16:34 +08:00
    whoami9894
        1
    whoami9894  
       2018-08-30 10:12:21 +08:00 via Android
    list 对象每次创建都会创建 id 值不同的新对象

    不同的是字符串驻留和小整数驻留机制,[A-Za-z0-9_]的字符串,-5 ~ 256 的小整数新建对象时不会 copy
    mimzy
        2
    mimzy  
       2018-08-30 10:26:41 +08:00 via Android
    一楼正解

    如果按你那么理解的话,Univs1 恰好创建了和 Univs 相同的内容,因此指向同一对象的话,那修改 Univs 也会造成 Univs1 的变动,这明显是不合理的。
    lxy42
        4
    lxy42  
       2018-08-30 11:07:47 +08:00
    最近正在看《 Python 源码剖析》
    #1 已经说到了几点,我补充一下:

    - 小整数缓存机制,Python 内部会预先初始化一个小整数对象缓存池,范围是[-5, 256],在创建该范围内的整数时直接使用缓存池中的整数对象。

    ```
    >>> a = 1
    >>> id(a)
    140706733650600
    >>> b = 1
    >>> id(b)
    140706733650600
    ```

    - 字符串缓存机制,空字符串会被缓存在 nullstring,长度为 1 的字符串(即 0 - 255 的字符)会缓存在长度为 256 的 characters 数组中,避免重复创建。长度超过 1 的字符串会缓存在 intered 的字典中。


    ```
    >>> a = '^'
    >>> id(a)
    4466954032
    >>> b = '^'
    >>> id(b)
    4466954032
    >>>
    ```

    - list 和 dict 也都有对应的缓存机制,当一个 list 或者 dict 销毁时,并不是真正的从内存中抹去,而是标记为“ free object ”,下次要创建 list 或者 dict 时,可以直接使用上次销毁的对象。

    ```
    >>> a = [1, 2, 3]
    >>> id(a)
    4467181832
    >>> del a
    >>> a
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    NameError: name 'a' is not defined
    >>> b = [1, 2, 3, 4]
    >>> id(b)
    4467181832
    >>>
    ```
    lxy42
        5
    lxy42  
       2018-08-30 11:16:34 +08:00
    > 按照我自己的理解,如果 name bind 能够找到一个完全相同的 object,就不会重新创建一份 copy

    这样做我觉得会有两个问题:
    1. 在作用域中查找是否存在相同的 object 会带来性能问题。
    2. Univs 和 Univs1 虽然看似值是相等的,但是它们是两个赋值过程,理应创建不同的 list。list 是可变类型,如果两者引用同一个 list,修改其中一个时会影响另外一个。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3469 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 11:40 · PVG 19:40 · LAX 04:40 · JFK 07:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.