如果两个变量指向同一个对象,为什么不重新分配一个变量会影响另一个变量?

发布于 2021-01-29 19:31:19

我试图了解变量如何在python中工作。说我有一个对象存储在变量中a

>>> a = [1, 2, 3]

如果我分配ab,则它们都指向同一个对象:

>>> b = a
>>> b is a
True

但是,如果我重新分配ab,那就不再正确了:

>>> a = {'x': 'y'}
>>> a is b
False

这两个变量现在具有不同的值:

>>> a
{'x': 'y'}
>>> b
[1, 2, 3]

我不明白为什么变量现在不同。为什么a is b不再是真的?有人可以解释发生了什么吗?

关注者
0
被浏览
133
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    Python具有引用 对象的 名称 。对象与名称分开存在,名称与它们引用的对象分开存在。 __

    # name a
    a = 1337
        # object 1337
    

    在为“名称分配名称”时,右侧 评估 所引用的对象。类似于如何2 + 2评估4a评估原始1337

    # name b
    b = a
        # object referred to by a -> 1337
    

    在这一点上,我们有a -> 1337b -> 1337-注意,无论名字知道对方!如果我们测试a is b,则两个名称都被 评估
    为同一个对象,这显然相等。

    重新分配名称只会更改该名称所指的内容-也没有可以更改其他名称的连接。

    # name a - reassign
    a = 9001
      # object 9001
    

    此时,我们有a -> 9001b -> 1337。如果我们现在测试a is b,则两个名称将被 评估 为不同的不同对象。


    如果您来自诸如C之类的语言,那么您将习惯于 包含 值的变量。例如,char a = 12可以读取为“a是包含12”的存储区域。最重要的是,您可以让多个变量使用相同的内存。将另一个值分配给变量会更改共享内存的内容,因此也会更改两个变量的值。

    +- char a -+
    |       12 |
    +--char b -+
    
    # a = -128
    
    +- char a -+
    |     -128 |
    +--char b -+
    

    这不是Python的工作方式:名称不包含任何内容,而是引用单独的值。例如,a = 12可以读取为“a是指值的名称12”。最重要的是,您可以有多个名称引用相同的值-
    但它仍将是单独的名称,每个名称都有其自己的引用。为名称分配另一个值会更改该名称的引用-但不会影响其他名称的引用。

    +- name a -+ -\
                   \
                    --> +- <12> ---+
                   /    |       12 |
    +- name b -+ -/     +----------+
    
    # a = -128
                        +- <-128> -+
    +- name a -+ -----> |     -128 |
                        +----------+
    
                        +- <12> ---+
    +- name b -+ -----> |       12 |
                        +----------+
    

    令人困惑的一点是, 可变 对象似乎违反了名称和对象的分隔。通常,这些是容器(例如listdict…),并且类在默认情况下表现出相同的行为。

    # name m
    m = [1337]
        # object [1337]
    # name n
    n = m
        # object referred to by m
    

    与普通整数类似,包含整数1337的列表[1337]一个 可以由多个独立名称引用 的对象 。如上所述,n is m评估为Truem = [9001]不变n

    但是,对名称的某些操作会更改名称 和所有别名所 看到的值。

    # inplace add to m
    m += [9001]
    

    此操作之后,m == [1337, 9001] n is m仍然适用。实际上,byn所看到的值也已更改为[1337, 9001]。这似乎违反了上述行为,在别名中,别名互不影响。

    这是因为m += [9001]没有更改m所指的内容。它仅更改引用的列表(和别名)的 内容 。双方并仍然指向原始列表对象,它的
    被改变。m``n``m``n __

    +- name m -+ -\
                   \                  
                    --> +- […] -+     +--- <@0> -+
                   /    |    @0 |  -> |     1337 |
    +- name n -+ -/     +-------+     +----------+
    
    # m += [9001]
    
    +- name m -+ -\
                   \                  
                    --> +- […] -+     +--- <@0> -++--- <@1> -+
                   /    | @0 @1 |  -> |     1337 ||     9001 |
    +- name n -+ -/     +-------+     +----------++----------+
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看