ps复制后怎么放大,python切片是深拷贝还是浅拷贝

  ps复制后怎么放大,python切片是深拷贝还是浅拷贝

  在Python中,对象的赋值和复制(深/浅复制)是有区别的。如果使用时不注意,可能会有意想不到的效果。

  让我们根据原文仔细理解这些区别:

  对象分配

  让我们看看下面的代码部分:

  In [1]: will=[will ,28,[python , C# , Javascript]]

  在[2]中:威尔伯=威尔

  在[3]: id(将)

  Out[3]: 2335727905096

  在[4]中:id(wilber)

  Out[4]: 2335727905096

  in[5]:print([遗嘱中ele的id(ele])

  [2335725285536, 1453458736, 2335727904456]

  in[6]:print([Wilber中ele的id(ele])

  [2335725285536, 1453458736, 2335727904456]

  In [7]: will[0]=wilber

  在[8]:会[2]。追加( CSS )

  在[9]: id(将)

  Out[9]: 2335727905096

  在[10]: id(威尔伯)

  Out[10]: 2335727905096

  in[11]:print([遗嘱中ele的id(ele])

  [2335727892328, 1453458736, 2335727904456]

  in[12]:print([Wilber中ele的id(ele])

  [2335727892328, 1453458736, 2335727904456]

  让我们分析一下这段代码:

  首先创建一个名为will的变量,该变量指向一个list对象,从第一张图就可以看出所有对象的地址(每次运行的结果可能都不一样)

  然后将wilber变量赋给will变量,wilber变量将指向will变量对应的对象(内存地址),即“wilber is will”和“wilber[i] is will[i]”

  可以理解,在Python中,对象的赋值都是传递对象引用(内存地址)。

  在第三张图中,由于will和wilber指向同一个对象,所以对will的任何修改都会反映到wilber中。

  这里需要注意的是,str是一个不可变的类型,所以修改的时候会替换旧的对象,产生一个新的地址。

  为了便于理解,我直接复制了原图,里面的内存地址号和代码不一致。

  粘贴_图像. png

  浅拷贝

  让我们看看轻拷贝。

  在[1]中:导入副本

  In [2]: will=[Will ,28,[Python , C# , JavaScript]]

  In [3]: wilber=copy.copy(will)

  在[4]: id(将)

  Out[4]: 2899569681288

  在[5]中:id(wilber)

  Out[5]: 2899583552712

  in[6]:print([遗嘱中ele的id(ele])

  [2899583263664, 1453458736, 2899585719944]

  in[7]:print([Wilber中ele的id(ele])

  [2899583263664, 1453458736, 2899585719944]

  在[8]中:will[0]=wilber

  在[9]:将[2]。追加( CSS )

  在[10]: id(将)

  Out[10]: 2899569681288

  在[11]: id(威尔伯)

  Out[11]: 2899583552712

  in[12]:print([遗嘱中ele的id(ele])

  [2899586038616, 1453458736, 2899585719944]

  in[13]:print([Wilber中ele的id(ele])

  [2899583263664, 1453458736, 2899585719944]

  [14]:将

  Out[14]: [wilber ,28,[Python , C# , JavaScript , CSS]]

  在[15]:威尔伯

  Out[15]: [Will ,28,[Python , C# , JavaScript , CSS]]

  分析这段代码:

  首先,仍然使用一个will变量来指向list类型的对象。

  然后复制模块中的浅复制函数copy()对will指向的对象进行浅复制,然后将浅复制生成的新对象赋给wilber变量。

  浅层拷贝创建了一个新对象,在这个例子中,“wilber不是will”

  但对于对象中的元素,浅拷贝只使用原元素的引用(内存地址),即“wilber[i] is will[i]”

  当威尔被修改的时候,

  由于列表的第一个元素是不可变的类型,因此对应于will的列表的第一个元素将由一个新的对象来表示。

  但是列表的第三个元素是可变类型,修改操作不会产生新的对象,所以will的修改结果会相应的反映给wilber。

  粘贴_图像. png

  总而言之,当我们使用下面的操作时,就会产生浅层复制的效果:

  使用切片[:]操作

  使用工厂函数(如list/dir/set)

  使用复制模块中的copy()函数。

  深层拷贝

  最后,我们来看深层文案。

  在[1]中:导入副本

  In [2]: will=[Will ,28,[Python , C# , JavaScript]]

  in[3]:Wilber=copy . deep copy(will)

  在[4]: id(将)

  Out[4]: 2871945438664

  在[5]中:id(wilber)

  Out[5]: 2871945199048

  in[6]:print([遗嘱中ele的id(ele])

  [2871945176264, 1453458736, 2871945207496]

  in[7]:print([Wilber中ele的id(ele])

  [2871945176264, 1453458736, 2871945341256]

  在[8]中:will[0]=wilber

  在[9]:将[2]。追加( CSS )

  在[10]:将

  Out[10]: [wilber ,28,[Python , C# , JavaScript , CSS]]

  在[11]: id(将)

  Out[11]: 2871945438664

  在[12]: id(威尔伯)

  Out[12]: 2871945199048

  在[13]:威尔伯

  Out[13]: [Will ,28,[Python , C# , JavaScript]]

  in[14]:print([遗嘱中ele的id(ele])

  [2871945496928, 1453458736, 2871945207496]

  in[15]:print([Wilber中ele的id(ele])

  [2871945176264, 1453458736, 2871945341256]

  分析这段代码:

  首先,也使用一个will变量指向list类型的对象。

  然后通过复制模块中的深度复制函数deepcopy()对will指向的对象进行深度复制,然后将深度复制生成的新对象赋给wilber变量。

  类似于浅层拷贝,深层拷贝也会创建一个新对象,在这个例子中,“wilber is not will”

  但是,对于对象中的元素,深度复制会重新生成一个副本(有特殊情况,下面会解释),而不是简单地使用原始元素的引用(内存地址)。

  示例中,will的第三个元素指向2871945207496,而wilber的第三个元素是一个全新的对象2871945341256,即“wilber[2]不是will[2]”

  当威尔被修改的时候,

  由于列表的第一个元素是不可变的类型,所以对应于will的列表的第一个元素将使用新的对象2871945496928。

  但是列表的第三个元素是可变类型,修改操作不会产生新的对象,但是因为“wilber[2]不是will[2]”,所以Will will的修改不会影响wilber。

  粘贴_图像. png

  复制的特殊情况

  实际上,复制有一些特殊情况:

  对于非容器类型(如数字、字符串和其他“原子”类型的对象)没有复制这回事。

  也就是说,对于这些类型,“obj是copy.copy(obj)”和“obj是copy.deepcopy(obj)”

  如果祖先变量仅包含原子类型对象,则不能对其进行深度复制。请参见下面的示例。

  In [16]: book=(python , c# , Javascript )

  在[17]: copies=copy.deepcopy(书)

  [18]:本书是册

  Out[18]:真

  In [19]: book=(python , c# , Javascript ,[])

  在[20]: copies=copy.deepcopy(书)

  [21]:本书是册

  Out[21]:假

  本文介绍了对象的赋值和复制,以及它们之间的区别:

  在Python中,对象的赋值就是传递对象引用(内存地址)。

  使用copy.copy()创建对象的浅表副本。它复制对象,但仍使用对象中元素的原始参考。

  如果需要复制容器对象及其所有元素(包括其子元素),可以使用copy.deepcopy()进行深度复制。

  对于非容器类型(如数字、字符串和其他“原子”类型的对象),没有副本。

  如果元组变量只包含原子类型对象,则不能对其进行深度复制。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: