如何在Python中将None分配给对象引用

时间:2018-11-14 14:06:28

标签: python oop pass-by-reference

我是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对象也不要变成“无”吗?

3 个答案:

答案 0 :(得分:2)

None不应为o2 = None

在执行行o2时,o1不再引用None对象。现在,它引用o1对象。 o2id现在引用内存中的两个不同对象,如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看到的原因-修改了o2o1都引用的 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

诀窍在于,尽管o1o2是分开的,但o1.datao2.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.

重新分配后,对象之间便没有任何关系(除非通过其他方式捆绑在一起),并且合理地讲,您不应期望它们的行为相同。