我是python的新手,对以下代码的输出几乎不感到困惑。
class obj:
def __init__(self, data):
self.data = data
o1 = obj(2)
o2 = o1
def func1(obj):
obj.data = 5
func1(o1)
print(o1.data)
print(o2.data)
o2 = None
print(o1)
print(o2)
输出:
5
5
<__main__.obj instance at 0x7f7f6b5e63f8>
None
o1对象也不要变成“无”吗?
答案 0 :(得分:2)
None
不应为o2 = None
。
在执行行o2
时,o1
不再引用None
对象。现在,它引用o1
对象。 o2
和id
现在引用内存中的两个不同对象,如id
函数所示(不同的标识,CPython
返回print (id(o1)) # 140282748479024
print (id(o2)) # 140282748479024
o2 = None
print (id(o1)) # 140282748479024
print (id(o2)) # 140282774063376
中的对象内存地址)
{{1}}
答案 1 :(得分:2)
Python中的变量是对象的名称,而不是C ++中的内存位置。重新分配名称仅会更改名称所指的含义;它不会更改引用对象或其他别名。
最接近的等效项是一个指针:在CPython中,像o2 = o1
中那样分配名称实际上意味着PyObject *o2 = *o1
。地址是从一个名字复制到另一个名字的。分配后的名称之间没有直接关系-它们恰好仍然引用相同的对象。
>>> o1 = {1, 2, 3}
>>> o2 = o1
>>> print(id(o1), id(o2)) # the *referents* of o1 and o2 are at the same memory location
4444160520 4444160520
当两个名称引用相同的对象时,它们表示该对象的相同状态-毕竟只有一个状态。这就是为什么更改o1.data
也可以通过o2
看到的原因-修改了o2
和o1
都引用的 object 。
>>> o1.add(16)
>>> print(o1, o2) # still the same referent, should have the same state
{16, 1, 2, 3} {16, 1, 2, 3}
>>> print(id(o1), id(o2)) # both still have the same referent
4444160520 4444160520
诀窍在于,尽管o1
和o2
是分开的,但o1.data
和o2.data
之类的成员却不是!每个顶级名称都是一个单独的实体。但是,属性等是相对于其对象的!
重新分配时,只会更改分配给它的名称。请记住,o2
是从o1
复制过来的-更改名称o1
不会影响任何关系。
>>> o1 = None
>>> print(o1, o2) # not the same referent anymore
None {16, 1, 2, 3}
>>> print(id(o1), id(o2)) # only o2 still refers to the same referent
4436169032 4444160520
答案 2 :(得分:0)
第o2 = None
行实际上被重新分配为与o1
不同的对象。观察:
>>> o1 = obj(2)
>>> id(o1)
155034832
>>> o2 = o1
>>> id(o2)
155034832 # same ID as o1
>>> o1 is o2
True # the objects are identical
但是一旦您重新分配了o2
:
>>> o2 = None
>>> id(o2)
262150788 # ID has now changed
>>> o1 is o2
False # the objects are now different.
重新分配后,对象之间便没有任何关系(除非通过其他方式捆绑在一起),并且合理地讲,您不应期望它们的行为相同。