python是否在分配时复制对象?

时间:2015-01-07 05:12:17

标签: python copy assign

我读到python中的assign不复制它的工作方式就像它在c中指定一个指向对象的指针一样。

但是当我调试这个函数时:

def popall(self):
    objs = self.curstack
    self.curstack = []
    return objs

看起来某种副本正在发生。在此功能运行后,obis充满了各种东西, self.curstack 是空的......

所以正在进行一些复制。是深还是浅?

5 个答案:

答案 0 :(得分:4)

它不会复制任何东西。只是分配给self.curstack并不会修改用于引用的self.curstack。只是让self.curstack引用其他内容。

这样想。 self.curstack指向一些东西。使用objs = self.curstack,您objs指向相同的内容。使用self.curstack = [],您可以将self.curstack指向一个空列表。这并不能删除self.curstack过去指出的任何内容;那些东西还在那里,objs仍指着它。

This article使用标签标签的一个很好的类比来解释它。

答案 1 :(得分:2)

Python在任何地方都使用引用。所以你的代码就像这样:

objs = self.curstack

现在objs指向任何curstack

self.curstack = []

现在curstack指向一个空列表。 objs未更改,并指向旧curstack

return objs

您返回objs,这是旧版curstack

答案 2 :(得分:2)

正如self.curstack未对其进行修改的所有答案所述,只需提及某些内容即可。在你的情况下,它指的是一个空列表[]

您实际上可以使用swampy

查看对象的引用方式
 from swampy.Lumpy import Lumpy

class ref_test:

    def __init__(self, curstack):
        self.curstack = curstack

    def popall(self): 
        lampy = Lumpy()
        objs = self.curstack 
        self.curstack = [] 
        print id(self.curstack), id(objs)
        lampy.object_diagram()
        return objs

o = ref_test([1,2,3,4])
res = o.popall()
print res

enter image description here

正如您所看到的,self.curstack指向一个空列表,而objs仍然保留了self.curstack的旧值。

您可以使用id函数来检查对象的“身份”。对于self.curstackobjs

,我们的情况并不是唯一的
164711692 163838732

答案 3 :(得分:0)

让我们演示一下究竟发生了什么(使用显示内存位置的id

a = [1,2,3]
print id(a)
b = a
print id(b)
a = 4
print id(a)
print a
print b
  

4339130240

     

4339130240

     

4298163184

     

4

     

[1,2,3]

因此ab最初指向内存中的相同位置,但随后a指向某个新位置。但是现在,让我们试试

a = [1,2,3]
print id(a)
b = a
print id(b)
a[0] = 4
print id(a)
print a
print b
  

4339098040

     

4339098040

     

4339098040

     

[4,2,3]

     

[4,2,3]

所以b不是a的全新副本。它与a(当它被定义时)是同一个对象。如果你那么a=4,你告诉python,让我们忘记a过去指向的内容并为其赋予新的含义。 4不会出现在a用于引用的内存中。相反,a现在指的是记忆中的新位置。 b仍然指的是a最初提到的内容。

如果我们不重新分配a,而是更改a指向的对象中的某个内容,则检查b会显示相应的更改发生在{ {1}}。

答案 4 :(得分:0)

在Python中,有两个空格,命名空间和对象空间。

名称只是您分配给对象的标签,它们位于对象空间中。对象具有值和类型;名字只是为了我们的方便;这样我们就可以访问对象空间中的东西。

这与C之类的其他语言不同,其中变量更像是一个盒子,你可以放置某种类型的东西。

在Python中,名称可以指向任何类型的任何对象 - 它们只是别名。

为对象指定名称时,如下所示:

a = 1

a只是一个标签,指向具有类型(int)和值的对象1。如果你接下来这样做:

b = 1

现在您有两个名称ab指向同一个对象 - 它们不是"副本",而只是两个标签指向同一个对象。

执行此操作时:

a = 'hello'

现在a指向一个新对象,但b仍然指向旧对象(1)。

最终,当没有名称指向对象时,Python会自动进行垃圾回收以保持对象空间的优化。