当前位置: 首页 > 面试题库 >

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

谢华彩
2023-03-14
问题内容

我试图了解变量如何在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不再是真的?有人可以解释发生了什么吗?


问题答案:

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 -+ -/     +-------+     +----------++----------+


 类似资料:
  • 问题内容: 我总是理解静态变量在被引用时共享一个实例。我想对此进行测试,但结果与我预期的不同。 输出: 柜台:1 测试:0 由于引用我认为,当我增加那么将自动以及递增。但是,似乎是从某处引用,问题是在哪里? 问题答案: 由于引用 这个假设是错误的。在Java中,您不能引用变量。变量中存储的是一个值。该值可以是原始类型值或引用类型值。对于基元,值是基元的值。对于引用类型, 引用值(通常只是引用)是指

  • 问题内容: 我想了解原始和对象引用变量的行为方式不同。我以Kathy Sierra的 OCA / OCP Java SE7中 的以下代码为例: 在上面的代码中,我获得了更改之前和之后的值。 基本变量case的输出为: 但是,在对象引用变量中,一旦更改了的值,我将获得不同的值 参考变量大小写的输出为: 书中提到在两种情况下都复制位模式并放置新副本。如果这是真的,那为什么我们会得到不同的行为呢? 问题

  • 问题内容: 我在Javascript中有一组全局计数器变量: 等等 然后,我有了一个Javascript函数,该函数接受一个映射到这些全局计数器的“索引”数字。在此函数内部,我需要使用传递给该函数的“索引”值来读写这些全局计数器。 我希望它如何工作的示例,但当然根本不起作用: 我希望我要实现的目标是明确的。如果没有,我会尽力澄清。谢谢。 编辑说明: 我不是要增加计数器的名称,而是要增加计数器包含的

  • 问题内容: 这是我学习python的第二天(我了解C ++和一些OOP的基础知识),并且我对python中的变量有些困惑。 这是我目前对它们的了解: Python变量是对对象(可变或不可变)的引用(或指针?)。当我们有类似的内容时,不可变对象将在内存中的某个位置创建,而名称- 对象引用对将在某个命名空间中创建。当我们拥有时,不会复制任何内容,但是现在两个变量都引用相同的对象,并被添加到相同的名称空

  • 问题内容: 我有一个嵌套的字典,我们称它为字典d。该词典的键是一个整数,每个键的值是另一个词典。我正在python 2.7上尝试一个简单的代码来更新一个外键的值,但似乎它正在更新外键的ALL的值。 希望这些代码将使其更易于理解。这是我的意见。 然后是输出: 您会看到,我只为d [0] [‘mean’]分配了‘1’,但是d [1] [‘mean’]也有所更新。如果我增加d键的数量,它将只更改所有d键

  • 问题 下面的代码显示,当影响一个数组到另一个数组时,这两个数组变得相互依赖。 我想知道为什么这与类型不同,因为如果我们有以下内容: 两个变量和引用的是同一个字符串,所以更改一个会影响另一个。