Shallow copy and Deep copy

一、来自wikipidia的解释:

Shallow copy

One method of copying an object is the shallow copy. In that case a new object B is created, and the fields values of A are copied over to B. This is also known as a field-by-field copy,field-for-field copy, or field copy. If the field value is a reference to an object (e.g., a memory address) it copies the reference, hence referring to the same object as A does, and if the field value is a primitive type it copies the value of the primitive type. In languages without primitive types (where everything is an object), all fields of the copy B are references to the same objects as the fields of original A. The referenced objects are thus shared, so if one of these objects is modified (from A or B), the change is visible in the other. Shallow copies are simple and typically cheap, as they can be usually implemented by simply copying the bits exactly.

复制对象的一种方法是浅拷贝。 在这种情况下,将创建一个新对象B,并将A的字段值复制到B.这也称为逐字段复制,或字段复制。 如果字段值是对对象(例如,存储器地址)的引用,则它复制引用,因此引用与A相同的对象,并且如果字段值是原始类型,则它复制原始类型的值。 在没有原始类型的语言(其中一切都是对象)中,副本B的所有字段都引用与原始A的字段相同的对象。因此,共享引用的对象,因此如果这些对象中的一个被修改(从A 或B),变化在另一个中可见。 浅拷贝很简单,通常很便宜,因为它们通常可以通过简单地复制这些位来实现。

Deep copy

An alternative is a deep copy, meaning that fields are dereferenced: rather than references to objects being copied, new copy objects are created for any referenced objects, and references to these placed in B. The result is different from the result a shallow copy gives in that the objects referenced by the copy B are distinct from those referenced by A, and independent. Deep copies are more expensive, due to needing to create additional objects, and can be substantially more complicated, due to references possibly forming a complicated graph.

另一种方法是深拷贝,意思是字段被解引用:而不是对被拷贝的对象的引用,为任何引用的对象创建新的拷贝对象,并且将这些对象的引用放置在B.结果不同于浅拷贝给出的结果 因为副本B引用的对象与A引用的对象不同,并且是独立的。 由于需要创建附加对象,深拷贝更加昂贵,并且由于可能形成复杂图形的引用,可能显着更复杂。

In Python, the library‘s copy module provides shallow copy and deep copy of objects through the copy() and deepcopy() functions, respectively.Programmers may define special methods __copy__() and __deepcopy__() in an object to provide custom copying implementation.

In VBA, an assignment of variables of type Object is a shallow copy, an assignment for all other types (numeric types, String, user defined types, arrays) is a deep copy. So the keyword Set for an assignment signals a shallow copy and the (optional) keyword Let signals a deep copy. There is no built-in method for deep copies of Objects in VBA.

二、来自Python的List实例

在Python中,引用是指从变量到对象的连接,即保存的值为对象的地址,它是一种关系,以内存中的指针形式实现。

在Python中,一个变量保存的值除了基本类型保存的是值外,其它都是引用。

变量:是一个系统表的元素,拥有指向对象连接的空间。

对象:是被分配的一块内存,有足够的空间去表现它们所代表的值。

引用:自动形成的从变量到对象的指针。

共享引用:

>>> L1 = [1, 2, 3]
>>> L2 = L1
>>> L1.append(4)>>> L2
>>> [1, 2, 3, 4]L1与L2指向内存中的同一对象,对其中一个对象的修改都会影响另一个对象的值,即L1与L2共享引用对象。

解决方法:

>>> L1 = [1, 2, 3]>>> L2 = L1.copy()  # list.copy()-->Return a shallow copy of the list. Equivalent to a[:].>>> L1.append(4)>>> L1>>> [1, 2, 3, 4]>>> L2>>> [1, 2, 3]

以上例子只适用于简单列表,也就是列表中的元素都是基本类型,如果列表元素还存在列表的话,这种方法就不适用了。原因就是,象a.copy()这种处理方法,只是将列表元素的值生成一个新的列表,如果列表元素也是一个列表,如:a=[1,2,3,4,[‘a‘,‘b‘]],那么这种复制对于元素[‘a‘,‘b‘]的处理只是复制[‘a‘,‘b‘]的引用,而并未生成 [‘a‘,‘b‘]的一个新的列表复制。代码如下:

>>> a = [1, 2, 3, 4, [‘a‘, ‘b‘]]
>>> b = a.copy()
>>> a[4].append(‘c‘)
>>> b
>>> [1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘]]

解决方法:copy模块,请参考第三节。

三、来自Python的模块copy

copy — Shallow and deep copy operations

Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other. This module provides generic shallow and deep copy operations (explained below).

Interface summary:

copy.copy(x)  -->Return a shallow copy of x.
Shallow copy operation on arbitrary Python objects.
See the module‘s __doc__ string for more info.
copy.deepcopy(x)  -->Return a deep copy of x.

deepcopy(x, memo=None, _nil=[])

Deep copy operation on arbitrary Python objects.

See the module‘s __doc__ string for more info.

exception copy.error  -->Raised for module specific errors.

The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):

  • A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
  • A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

Two problems often exist with deep copy operations that don’t exist with shallow copy operations:

  • Recursive objects (compound objects that, directly or indirectly, contain a reference to themselves) may cause a recursive loop.
  • Because deep copy copies everything it may copy too much, e.g., administrative data structures that should be shared even between copies.

The deepcopy() function avoids these problems by:

  • keeping a “memo” dictionary of objects already copied during the current copying pass; and
  • letting user-defined classes override the copying operation or the set of components copied.

This module does not copy types like module, method, stack trace, stack frame, file, socket, window, array, or any similar types. It does “copy” functions and classes (shallow and deeply), by returning the original object unchanged; this is compatible with the way these are treated by the pickle module.

Shallow copies of dictionaries can be made using dict.copy(), and of lists by assigning a slice of the entire list, for example, copied_list = original_list[:].

Classes can use the same interfaces to control copying that they use to control pickling. See the description of module pickle for information on these methods. In fact, the copy module uses the registered pickle functions from the copyreg module.

In order for a class to define its own copy implementation, it can define special methods __copy__() and __deepcopy__(). The former is called to implement the shallow copy operation; no additional arguments are passed. The latter is called to implement the deep copy operation; it is passed one argument, the memo dictionary. If the __deepcopy__() implementation needs to make a deep copy of a component, it should call the deepcopy() function with the component as first argument and the memo dictionary as second argument.

See also

Module pickle
Discussion of the special methods used to support object state retrieval and restoration. 

实例:

>>> import copy
>>> a = [1, 2, 3, 4, [‘a‘, ‘b‘]]
>>> b = a
>>> c = copy.copy(a)
>>> d = copy.deepcopy(a)>>> a.append(5)
>>> a[4].append(‘c‘)

>>> a>>> [1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘], 5]
>>> b
>>> [1, 2, 3, 4, [‘a‘, ‘b‘,‘c‘], 5]
>>> c
>>> [1, 2, 3, 4, [‘a‘, ‘b‘,‘c‘]]
>>> d
>>> [1, 2, 3, 4, [‘a‘, ‘b‘]]

参考文章:

[1] --> https://en.wikipedia.org/wiki/Object_copying#Shallow_copy

[2] --> http://www.jb51.net/article/64030.htm

[3] --> http://www.jb51.net/article/15714.htm

[4] --> https://docs.python.org/3/library/copy.html

[5] --> Learning Python 3rd Edition

时间: 2024-08-06 09:03:02

Shallow copy and Deep copy的相关文章

python中的shallow copy 与 deep copy

今天在写代码的时候遇到一个奇葩的问题,问题描述如下: 代码中声明了一个list,将list作为参数传入了function1()中,在function1()中对list进行了del()即删除了一个元素. 而function2()也把list作为参数传入使用,在调用完function1()之后再调用function2()就出现了问题,list中的值已经被改变了,就出现了bug. 直接上代码: list = [0, 1, 2, 3, 4, 5] def function1(list): del lis

NumPy学习(索引和切片,合并,分割,copy与deep copy)

NumPy学习(索引和切片,合并,分割,copy与deep copy) 目录 索引和切片 合并 分割 copy与deep copy 索引和切片 通过索引和切片可以访问以及修改数组元素的值 一维数组 程序示例 import numpy as np #索引与切片 array=np.arange(3,15) print(array) print(array[3])#数组下标为3的元素 print('\n') print(array[1:3])#取从下标1到下标3,不包括下标3 print(array[

copy&mutableCopy 浅拷贝(shallow copy)深拷贝 (deep copy)

本文来自 这里,原文作者微博MicroCai 概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对象内存到另一块内存中. 一图以蔽之 再简单些说:浅复制就是指针拷贝:深复制就是内容拷贝. 集合的浅复制 (shallow copy) 集合的浅复制有非常多种方法.当你进行浅复制时,会向原始的集合发送retain消息,引用计数加1,同时指针被拷贝到新的集合. 现在让我们看一些浅复制的例子: NSArray *shallowCop

Python 深浅拷贝 (Shallow copy and Deep copy in Python)

前言 昨天刷公众号看到一篇描述py优雅语法的文章,心痒之下到家就开始尝试,学习了for else statement,yield和py版三目写法.在列表切片这部分中,对作者的列表拷贝写法,有些不太理解. # 拷贝 copy_items = items[::] 或者 items[:] 尝试 首先开一个python,随便建一个列表l=[1,2,3]将其进行两种方法的拷贝: 我的写法 c=l 作者的写法 d=l[:] 分别打印了c和d,并没有什么差别,仔细斟酌了一下作者的用意,觉得应该有一些深层次的考

Summary: Deep Copy vs. Shallow Copy vs. Lazy Copy

Object copy An object copy is an action in computing where a data object has its attributes copied to another object of the same data type. An object is a composite data type in object-oriented programming languages. The copying of data is one of the

[C++] Deep copy ,Shallow copy, copy constructor,"="

Deep copy ,Shallow copy, copy constructor,"=" Dog.h #pragma once class Dog { public: char *name; Dog(); Dog(const Dog &it); ~Dog(); void operator =(const Dog &it); }; Dog.cpp #include "Dog.h" #include<string.h> #include&l

Java里的Deep Copy和Shallow Copy

以前从来没听说过这两个名词,这几天用List和Map的时候发现bug,才第一次在stackoverflow上知道有这么两个简单的专业术语可以形容我遇到的问题. 写下来的都是基于自己的理解,或许不准确,如果以后发现不对再回来修正. 首先,Java的数据类型只有两种:primitive type和object type. 基本数据类型(primitive type)在赋值的时候,只存在一种情况,因为他们的内存位置就是他们的实际值的位置,如果把一个变量赋值给另一个变量,也会在内存增加一个新的值. 对于

有关Ehcache的内容的引用和Java的deep copy

项目使用Ehcache来作为程序和数据库之间的缓冲, 使用过程中会对cache对象做修改, 如plan.setLangSymbol(),发现后面使用cache的地方,取到的数据都是修改后的,所以猜测是cache的浅引用造成的. 实际上,stackoverflow也有人提到此问题<Cache.get() returns deep copy of element?> 至于如何做deep copy,stackoverflow也提到<Copying cached Map<String ,

Deep Copy cv::StereoBM 深度拷贝

在使用OpenCV的三维立体重建的库时,一个重要的步骤就是生成左右视图的差异图Disparity,而控制生成disparity的参数的类是cv::StereoBM,我们有时候需要拷贝一份cv::StereoBM,然后改变其中的参数值,但是如果用默认的等号‘=’来进行拷贝,其实是浅拷贝,如果改变拷贝项的参数值,原来的参数值也会跟着改变,所以我们需要自己写一个深拷贝的函数,如下所示: /** * Deep copy cv::StereoBM bm1 to bm2 */ void copy_bm(co