Python:&;=操作人员
当我尝试使用Python:&;=操作人员,python,python-2.7,python-3.x,set,Python,Python 2.7,Python 3.x,Set,当我尝试使用&=和|=操作符来计算或/和两个集合时,我得到了一些奇怪的结果 s1 = {1,2,3} s2 = {2,3,4} tmp = s1 tmp &= s2 正如预期的那样,tmp将是{2,3},但我不知道为什么s1也将其值更改为{2,3} 但是,如果我这样做: tmp = tmp & s2 然后,s1将保持不变!有人能给我解释一下&=操作符下面发生了什么吗?它被称为交叉点\u update。返回集s只保留t中的元素。正如你在这张照片中看到的 您正在使用交叉点重新
&=
和|=
操作符来计算或/和两个集合时,我得到了一些奇怪的结果
s1 = {1,2,3}
s2 = {2,3,4}
tmp = s1
tmp &= s2
正如预期的那样,tmp将是{2,3},但我不知道为什么s1
也将其值更改为{2,3}
但是,如果我这样做:
tmp = tmp & s2
然后,
s1
将保持不变!有人能给我解释一下&=
操作符下面发生了什么吗?它被称为交叉点\u update
。返回集s只保留t中的元素。正如你在这张照片中看到的
您正在使用交叉点重新构建第一个集合。按值而不是参照复制集合
tmp = set(s1)
(由于s1
是set
的一个实例)对于set
的实现方式不同于
集合&=…
是使用更新集合的方法实现的
相关CPython代码(
Object/setobject.c
):
set\u iand(PySetObject*so,PyObject*other)
{
PyObject*结果;
如果(!PyAnySet_Check(其他))
Py_返回未执行;
result=set\u intersection\u update(so,other);//导致意外结果的不是&=
运算符,而是Python如何将对象存储在内存中,并使用变量(名称)引用它们
Python中的所有内容都是一个对象,它存储在内存中的某个位置。声明变量只会告诉Python您正在引用存储在内存中特定位置的特定对象,使用变量名作为对该对象的引用
您可以使用内置的id()
函数获取有关对象内存位置的一些信息,例如:
s1 = {1,2,3}
s2 = {2,3,4}
tmp = s1
id(tmp)
1763330653544
id(s1)
1763330653544
有关内置id()
函数的一些信息:
返回对象的“标识”。这是一个整数
保证此对象在运行期间唯一且恒定
生命周期。两个生命周期不重叠的对象可能具有相同的生命周期
id()值
CPython实现细节:这是内存中对象的地址
如您所见,通过使用id()
函数,名称tmp
和s1
引用的对象是相同的,因为返回的整数值是相同的
因此,当你改变其中一个时,另一个也会改变。实际上,我在最后一句中所说的在技术上是不正确的,因为内存中没有“要么”,只有一个集合对象,有两个不同的引用(tmp
和s1
)
但并不总是这么简单,所以如果您想了解这一点,我建议您查找Python内存管理和变量引用
真正的Python似乎很好地解释了对象引用(使用名称/变量)。您应该按值而不是按引用复制s1
s1 = {1,2,3}
s2 = {2,3,4}
tmp = s1
id(tmp)
1763330653544
id(s1)
1763330653544
s1 = {3, 4, 5}
s2 = s1
s2.add(6)
s1
{3, 4, 5, 6}
id(s1)
1763330653320
id(s2)
1763330653320