我是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对象不应该也变成"无"吗??
o1
不应该是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
Python中的变量是对象的名称,而不是C++中的内存位置。重新分配一个名称只会改变名称所指的内容;它不会更改referent或其他别名。
最接近的等价物是指针:在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
当两个名称引用同一个对象时,它们显示对象的相同状态——毕竟,只有一个状态。这就是为什么通过o2
也可以看到更改o1.data
的原因——o2
和o1
都引用的对象被修改了。
>>> 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
行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.
一旦重新分配,对象之间就没有任何关系(除非通过其他方式绑定(,合理地说,您不应该期望它们的行为相同。