python赋值运算符后如何赋值
How does python assign values after assignment operator
好吧,我确定这是一个非常愚蠢的问题。但是python如何给变量赋值呢?
假设有一个变量 a
并赋值 a=2
。因此 python 为变量分配了一个内存位置,而 a
现在指向包含值 2
的内存位置。现在,如果我分配一个变量 b=a
,变量 b
也指向与变量 a
相同的位置。
现在。如果我分配一个变量 c=2
它仍然指向与 a
相同的内存位置,而不是指向一个新的内存位置。那么,python 是如何工作的呢?它是否首先检查所有先前分配的变量以检查它们是否共享相同的值,然后为其分配内存位置?
此外,它与列表的工作方式不同。如果我分配 a=[2,3]
然后 b=[2,3]
并使用 id
函数检查它们的内存位置,我得到两个不同的内存 locations.But c=b
给我相同的位置。有人可以解释正确的工作方式和原因吗?
编辑:-
基本上我的问题是因为我刚刚开始学习 is
运算符并且显然只有当它们指向相同的位置时它才持有 True
。所以,如果 a=1000
和 b=1000
a is b
是 False
但是 a="world"
b="world"
它成立。
这是 python 针对小整数执行的优化。一般来说,你不能指望 a 和 c 指向同一个位置。如果你用逐渐变大的整数尝试这个实验,你会发现它在某个时候停止工作。我很确定 1000 足够大,但我不在电脑旁边;我想我记得它是从 -128 到 127 的所有整数都以这种方式处理(或其他一些 "round number")。
您的理解大体上是正确的,但值得注意的是 python 列表与 C 或 C++ 中的数组相比是完全不同的动物。来自文档:
id(对象)
Return 对象的“身份”。这是一个整数(或长整数),保证此对象在其生命周期内是唯一且不变的。具有 non-overlapping 生命周期的两个对象可能具有相同的 id() 值。
您问题的简单答案是 python 中的列表实际上是引用。这导致它们的内存地址不同,因为地址是引用的地址,而不是人们可能期望的对象。
我以前遇到过这个问题,我知道它会让人感到困惑。这里有两个概念:
- 一些数据结构是可变的,而另一些则不是
- Python 处理指针...大部分时间
所以让我们考虑列表的情况(您在使用整数时不小心偶然发现了内部和窥孔优化 - 我稍后会谈到)
所以让我们创建两个相同的列表(记住列表是可变的)
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 尝试保存 space。因此,它会在启动时将一些小东西加载到内存中(例如,小整数)。因此,当您将变量分配给一个小整数(如 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
并赋值 a=2
。因此 python 为变量分配了一个内存位置,而 a
现在指向包含值 2
的内存位置。现在,如果我分配一个变量 b=a
,变量 b
也指向与变量 a
相同的位置。
现在。如果我分配一个变量 c=2
它仍然指向与 a
相同的内存位置,而不是指向一个新的内存位置。那么,python 是如何工作的呢?它是否首先检查所有先前分配的变量以检查它们是否共享相同的值,然后为其分配内存位置?
此外,它与列表的工作方式不同。如果我分配 a=[2,3]
然后 b=[2,3]
并使用 id
函数检查它们的内存位置,我得到两个不同的内存 locations.But c=b
给我相同的位置。有人可以解释正确的工作方式和原因吗?
编辑:-
基本上我的问题是因为我刚刚开始学习 is
运算符并且显然只有当它们指向相同的位置时它才持有 True
。所以,如果 a=1000
和 b=1000
a is b
是 False
但是 a="world"
b="world"
它成立。
这是 python 针对小整数执行的优化。一般来说,你不能指望 a 和 c 指向同一个位置。如果你用逐渐变大的整数尝试这个实验,你会发现它在某个时候停止工作。我很确定 1000 足够大,但我不在电脑旁边;我想我记得它是从 -128 到 127 的所有整数都以这种方式处理(或其他一些 "round number")。
您的理解大体上是正确的,但值得注意的是 python 列表与 C 或 C++ 中的数组相比是完全不同的动物。来自文档:
id(对象) Return 对象的“身份”。这是一个整数(或长整数),保证此对象在其生命周期内是唯一且不变的。具有 non-overlapping 生命周期的两个对象可能具有相同的 id() 值。
您问题的简单答案是 python 中的列表实际上是引用。这导致它们的内存地址不同,因为地址是引用的地址,而不是人们可能期望的对象。
我以前遇到过这个问题,我知道它会让人感到困惑。这里有两个概念:
- 一些数据结构是可变的,而另一些则不是
- Python 处理指针...大部分时间
所以让我们考虑列表的情况(您在使用整数时不小心偶然发现了内部和窥孔优化 - 我稍后会谈到)
所以让我们创建两个相同的列表(记住列表是可变的)
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 尝试保存 space。因此,它会在启动时将一些小东西加载到内存中(例如,小整数)。因此,当您将变量分配给一个小整数(如 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