我确定,这是一个非常愚蠢的问题。但是python如何为变量赋值?
假设存在变量a=2
并为其分配值a
。所以python为变量分配一个内存位置,2
现在指向包含值b=a
的内存位置。现在,如果我分配变量b
,变量a
也指向与变量c=2
相同的位置。
现在。如果我分配变量a
,它仍然指向与a=[2,3]
相同的内存位置,而不是指向新的内存位置。那么,python是如何工作的?它是否首先检查所有先前分配的变量,以检查它们中的任何一个是否共享相同的值,然后为其分配内存位置?
此外,它与列表的工作方式不同。如果我分配b=[2,3]
然后id
并使用c=b
函数检查其内存位置,我会得到两个不同的内存位置。但是is
给了我相同的位置。有人可以解释正确的工作和原因吗?
编辑: -
基本上我的问题是因为我刚刚开始了解True
运算符,并且只有当它们指向同一位置时才会显示它a=1000
。因此,如果b=1000
和a is b
False
为a="world"
,b="world"
$ sed -r '1s/([a-zA-Z]:)0/\199999/' file
root:cDJZp9SHD2KhVgc:99999:0:99999:7:::
bin:*:12821:0:99999:7:::
daemon:*:12811:0:99999:7:::
adm:*:12811:0:99999:7:::
lp:*:12811:0:99999:7:::
则为真。
答案 0 :(得分:7)
我之前遇到过这个问题,并且明白它会让人感到困惑。这里有两个概念:
所以让我们考虑列表的情况(当你使用整数时,你不小心偶然发现了实习和窥视孔的优化 - 我稍后会谈到这一点)
因此,让我们创建两个相同的列表(记住列表是可变的)
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
尽管列表相同,但a
和b
是不同的内存位置。现在,这是因为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
看看那里发生了什么! a
和b
都分配到同一个内存位置。因此,您对其中所做的任何更改都将反映在另一个上。
最后,让我们简单谈谈我之前提到过的窥视孔。 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
答案 1 :(得分:0)
这是python为小整数执行的优化。通常,您不能指望指向同一位置的a和c。如果您尝试使用逐渐变大的整数进行此实验,您会发现它在某个时刻停止工作。我很确定1000足够大但我不在电脑附近;我想我记得从-128到127的所有整数都是以这种方式处理的(或其他一些"整数")。
答案 2 :(得分:0)
您的理解通常是正确的,但值得注意的是,与C或C ++中的数组相比,python列表是完全不同的动物。来自文档:
ID(OBJ) 返回对象的“标识”。这是一个整数(或长整数),保证在该生命周期内该对象是唯一且恒定的。具有非重叠生存期的两个对象可能具有相同的id()值。
你的问题的简单答案是python中的列表实际上是引用。这导致它们的内存地址不同,因为地址是引用的地址,而不是人们可能期望的对象。