python如何在赋值运算符之后赋值



好吧,我相信这是一个非常愚蠢的问题。但是python是如何为变量赋值的呢?

假设有一个变量a,并被赋予值a=2。因此,python为变量分配一个内存位置,a现在指向包含值2的内存位置。现在,如果我给变量b=a赋值,那么变量b也指向与变量a相同的位置。

现在。如果我分配一个变量c=2,它仍然指向与a相同的内存位置,而不是指向新的内存位置。那么,python是如何工作的呢?它是否首先检查所有先前分配的变量,以检查其中是否有共享相同的值,然后为其分配内存位置?

此外,它与列表的工作方式不同。如果我分配a=[2,3]b=[2,3],并用id函数检查它们的内存位置,我会得到两个不同的内存位置。但c=b给了我相同的位置。有人能解释一下正确的工作方式和原因吗?

编辑:-

基本上,我的问题是因为我刚刚开始学习is运算符,显然只有当它们指向同一位置时,它才会保持True。因此,如果a=1000b=1000 a is bFalse,而a="world" b="world"则成立。

我以前遇到过这个问题,我知道它会让人困惑。这里有两个概念:

  1. 有些数据结构是可变的,而另一些则不是
  2. Python可以关闭指针。。。大多数时候

因此,让我们考虑一个列表的情况(当你使用int时,你不小心偶然发现了内部和窥视孔优化——我稍后会讨论)

因此,让我们创建两个相同的列表(记住列表是可变的)

In [42]: a = [1,2]
In [43]: b = [1,2]
In [44]: id(a) == id(b)
Out[44]: False
In [45]: a is b
Out[45]: False

请参阅,尽管列表相同,但ab是不同的内存位置。现在,这是因为python计算[1,2],将其分配给一个内存位置,然后调用该位置a(或b)。python需要很长时间来检查每个分配的内存位置,看看[1,2]是否已经存在,并将b分配给与a相同的内存位置
更不用说列表是可变的,即您可以执行以下操作:

In [46]: a = [1,2]
In [47]: id(a)
Out[47]: 4421968008
In [48]: a.append(3)
In [49]: a
Out[49]: [1, 2, 3]
In [50]: id(a)
Out[50]: 4421968008

看到了吗?a保持的值已更改,但内存位置没有更改。现在,如果一堆其他变量名被分配到同一个内存位置,该怎么办?!它们也会被改变,这将是语言的一个缺陷。为了解决这个问题,python必须将整个列表复制到一个新的内存位置,因为我想更改a的值

即使是空列表也是如此:

In [51]: a = []
In [52]: b = []
In [53]: a is b
Out[53]: False
In [54]: id(a) == id(b)
Out[54]: False

现在,让我们谈谈我说过的关于指针的东西:

假设您希望两个变量实际上谈论相同的内存位置。然后,您可以将第二个变量分配给第一个变量:

In [55]: a = [1,2,3,4]
In [56]: b = a
In [57]: id(a) == id(b)
Out[57]: True
In [58]: a is b
Out[58]: True
In [59]: a[0]
Out[59]: 1
In [60]: b[0]
Out[60]: 1
In [61]: a
Out[61]: [1, 2, 3, 4]
In [62]: b
Out[62]: [1, 2, 3, 4]
In [63]: a.append(5)
In [64]: a
Out[64]: [1, 2, 3, 4, 5]
In [65]: b
Out[65]: [1, 2, 3, 4, 5]
In [66]: a is b
Out[66]: True
In [67]: id(a) == id(b)
Out[67]: True
In [68]: b.append(6)
In [69]: a
Out[69]: [1, 2, 3, 4, 5, 6]
In [70]: b
Out[70]: [1, 2, 3, 4, 5, 6]
In [71]: a is b
Out[71]: True
In [72]: id(a) == id(b)
Out[72]: True

看看那里发生了什么!CCD_ 32和CCD_。因此,您对其中一个所做的任何更改都将反映在另一个上。

最后,让我们简单地谈谈我之前提到的窥视孔的东西。Python试图节省空间。因此,它在启动时会将一些小东西加载到内存中(例如,小整数)。因此,当您将变量分配给一个小整数(如5)时,python不必在将值分配给内存位置并为其分配变量名之前计算5(与列表中的情况不同)。由于它已经知道5是什么,并将其隐藏在某个内存位置,所以它所做的就是为该内存位置分配一个变量名。然而,对于更大的整数,情况不再如此:

In [73]: a = 5
In [74]: b = 5
In [75]: id(a) == id(b)
Out[75]: True
In [76]: a is b
Out[76]: True
In [77]: a = 1000000000
In [78]: b = 1000000000
In [79]: id(a) == id(b)
Out[79]: False
In [80]: a is b
Out[80]: False

这是python对小整数执行的优化。一般来说,你不能指望a和c指向同一个位置。如果你用逐渐变大的整数进行这个实验,你会发现它在某个时候停止了工作。我敢肯定1000已经足够大了,但我离电脑不远;我记得从-128到127的所有整数都是这样处理的(或者其他一些"整数")。

您的理解通常是正确的,但值得注意的是,与C或C++中的数组相比,python列表是完全不同的动物。来自文件:

id(obj)返回对象的"标识"。这是一个整数(或长整数),保证在该对象的生存期内是唯一的和常量。寿命不重叠的两个对象可能具有相同的id()值。

这个问题的简单答案是python中的列表实际上是引用。这导致它们的内存地址不同,因为地址是引用的地址,而不是对象的地址。

最新更新