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的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。