Python:两个对象是相同的
可能重复:Python:两个对象是相同的,python,list,Python,List,可能重复: 此代码打印为True。为什么?只有当两个变量指向同一个对象时,“is”才会返回True,而在本例中,这两个变量是具有相同值的不同对象。“==”将返回True,但“is”不应返回True 但是, b.reverse() print a,b 打印[3,2,1][3,2,1],似乎就解释器而言,它们是同一个对象,对b的操作将自动对a执行。再说一遍,为什么?我以前从未见过这样的事情发生。它们实际上引用的是同一个对象 试试这个: a = [1,2,3] b = a print b is a
此代码打印为True。为什么?只有当两个变量指向同一个对象时,“is”才会返回True,而在本例中,这两个变量是具有相同值的不同对象。“==”将返回True,但“is”不应返回True 但是,
b.reverse()
print a,b
打印[3,2,1][3,2,1],似乎就解释器而言,它们是同一个对象,对b的操作将自动对a执行。再说一遍,为什么?我以前从未见过这样的事情发生。它们实际上引用的是同一个对象 试试这个:
a = [1,2,3]
b = a
print b is a
b[0] = 0
print b is a
您将看到a和b都已更改,并且彼此仍然相同
a = [1,2,3]
b = a
print b is a
您正在比较对同一列表的引用。如果您执行以下操作:
a = [1,2,3]
b = [1,2,3]
print b is a
你应该得到一个假的
a = [81, 82, 83]
b = a
print(a is b) #prints True
这就是这里实际发生的情况:
比如:
a = [81,82,83]
b = [81,82,83]
print(a is b) # False
print(a == b) #True, as == only checks value equality
何时使用该模块:
有关详细信息:
In [32]: def func():
....: a=[1,2,3]
....: b=a
....:
....:
In [34]: import dis
In [35]: dis.dis(func)
2 0 LOAD_CONST 1 (1)
3 LOAD_CONST 2 (2)
6 LOAD_CONST 3 (3)
9 BUILD_LIST 3
12 STORE_FAST 0 (a) #now 'a' poits to [1,2,3]
3 15 LOAD_FAST 0 (a) #load the object referenced by a
18 STORE_FAST 1 (b) #store the object returned by a to b
21 LOAD_CONST 0 (None)
24 RETURN_VALUE
In [36]: def func1():
....: a=[1,2,3]
....: b=[1,2,3]
....:
....:
In [37]: dis.dis(func1) #here both a and b are loaded separately
2 0 LOAD_CONST 1 (1)
3 LOAD_CONST 2 (2)
6 LOAD_CONST 3 (3)
9 BUILD_LIST 3
12 STORE_FAST 0 (a)
3 15 LOAD_CONST 1 (1)
18 LOAD_CONST 2 (2)
21 LOAD_CONST 3 (3)
24 BUILD_LIST 3
27 STORE_FAST 1 (b)
30 LOAD_CONST 0 (None)
33 RETURN_VALUE
我不确定列表的工作原理是否相同,但请看一看有关浅拷贝和深拷贝的numpy.array()教程:
a=b
只是创建对同一对象的新引用。要获得真正的副本,您可能会发现列表对象与链接中的深度副本示例类似,因此b=a.copy()
。然后可以说有两个引用指向两个具有相同值的独立对象
另外,我认为大多数OO语言都是这样工作的,=
只是创建了一个新引用,而不是一个新对象。当您执行a=[1,2,3]
时,您将名称a
绑定到一个列表对象。当您执行b=a
时,您将把名称b
绑定到a
是什么-在本例中是列表对象。因此,他们是一样的。。。一个对象可以有多个名称。这本书值得在网上阅读
如果您想制作listobj的副本,那么您可以查看b=a[:]
使用slice创建浅层副本,或者查看copy.copy
创建浅层副本(应适用于任意对象),或者查看copy.deepcopy
创建奇怪的深度副本
您还将注意到CPython中缓存短字符串/小整数的惊人之处
>>> a = 4534534
>>> b = a
>>> a is b
True
>>> b = 4534534
>>> a is b
False
>>> a = 1
>>> b = a
>>> a is b
True
>>> b = 1
>>> a is b
True
此代码打印为True。为什么?
因为b是一个
仅当两个变量指向同一对象时,“is”才返回True
如果它们命名相同的对象。“指向”是一个粗俗的术语,暗指一个低得多的编程模型
在这种情况下,它们是具有相同值的不同对象
不,他们不是
在Python中,b=a
意味着“b
将不再是当前名称的名称(如果有的话),而成为当前名称的名称”。同一个物体。没有复印件
Python中不会隐式复制内容
打印[3,2,1][3,2,1],似乎就解释器而言,它们是同一个对象
因为他们是
b上的操作将自动在a上执行
因为它们是同一个物体
再说一遍,为什么
再说一次,因为他们是
…就好像你想到了每一个明显的测试来证实你的行为,但是一旦每一个测试都与你的核心假设相矛盾,你就拒绝拒绝拒绝你的核心假设,即使文献中没有任何东西支持你的核心假设(因为事实上它是错误的)
我以前从未见过这样的事情发生
那么您以前一定从未在Python中测试过类似的东西,因为在Python中它一直都是这样工作的。编程语言之间甚至没有那么奇怪;Java对所有不是基元类型的东西都做同样的事情,C#对类(引用类型)做同样的事情,而对结构(值类型)做你显然期望的事情。它被称为“引用语义”,这绝不是一个新概念。“在这种情况下,它们是具有相同值的不同对象”我认为不是。是时候让您更好地学习Python了a
是对列表[1,2,3]
的引用,b=a
将a
中包含的引用分配给b
,因此现在它们包含对同一列表的引用。感谢您的快速响应。我尝试了a=[1,2,3]b=[1,2,3],这就解决了这个问题,但是对于我正在编写的代码来说,这是行不通的。如何让解释器知道,我想让它考虑一个和B不同的对象,这样B rReSESER()不改变一个“jjkneCKiE<代码> B= A[:]:/Cult>(浅拷贝)尝试复制类:@ JaveKeCKI:Cudio> [B:A[:] /<代码>将对简单列表进行操作,但是在列表的情况下,您需要<代码> Debug()
来自复制
模块。您需要副本做什么?你到底想做什么,为什么不问这个问题呢?你能解释一下为什么最后一个案例是真的吗?它看起来不一致,那么为什么它是这样设计的呢?在我看来,似乎只适用于整数btw(包括)-5到256,这是一个奇数间隔。@dan它也适用于单个字符(部分原因是256)。因为字符串和整数是不可变的,所以只保留一个常用值的副本是有意义的-5可能用于处理一些常见的错误代码,0和1经常使用,对于短循环或按位运算,0..256是有意义的。。。
In [1]: a=[1,2,3]
In [2]: b=a
In [3]: id(a),id(b)
Out[3]: (143186380, 143186380) #both point to the same object
In [4]: b=a[:] #now use slicing, it is equivalent to b=copy.copy(a)
# or b= list(a)
In [5]: id(a),id(b)
Out[5]: (143186380, 143185260) #as expected both now point to different objects
# so now changing one will not affect other
In [6]: a=[[1,2],[3,4]] #list of lists
In [7]: b=a[:] #use slicing
In [8]: id(a),id(b) #now both point to different object as expected
# But what about the internal lists?
Out[8]: (143184492, 143186380)
In [11]: [(id(x),id(y)) for (x,y) in zip(a,b)] #so internal list are still same objects
#so doing a[0][3]=5, will changes b[0] too
Out[11]: [(143185036, 143185036), (143167244, 143167244)]
In [12]: from copy import deepcopy #to fix that use deepcopy
In [13]: b=deepcopy(a)
In [14]: [(id(x),id(y)) for (x,y) in zip(a,b)] #now internal lists are different too
Out[14]: [(143185036, 143167052), (143167244, 143166924)]
In [32]: def func():
....: a=[1,2,3]
....: b=a
....:
....:
In [34]: import dis
In [35]: dis.dis(func)
2 0 LOAD_CONST 1 (1)
3 LOAD_CONST 2 (2)
6 LOAD_CONST 3 (3)
9 BUILD_LIST 3
12 STORE_FAST 0 (a) #now 'a' poits to [1,2,3]
3 15 LOAD_FAST 0 (a) #load the object referenced by a
18 STORE_FAST 1 (b) #store the object returned by a to b
21 LOAD_CONST 0 (None)
24 RETURN_VALUE
In [36]: def func1():
....: a=[1,2,3]
....: b=[1,2,3]
....:
....:
In [37]: dis.dis(func1) #here both a and b are loaded separately
2 0 LOAD_CONST 1 (1)
3 LOAD_CONST 2 (2)
6 LOAD_CONST 3 (3)
9 BUILD_LIST 3
12 STORE_FAST 0 (a)
3 15 LOAD_CONST 1 (1)
18 LOAD_CONST 2 (2)
21 LOAD_CONST 3 (3)
24 BUILD_LIST 3
27 STORE_FAST 1 (b)
30 LOAD_CONST 0 (None)
33 RETURN_VALUE
>>> a = 4534534
>>> b = a
>>> a is b
True
>>> b = 4534534
>>> a is b
False
>>> a = 1
>>> b = a
>>> a is b
True
>>> b = 1
>>> a is b
True