1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象。
2. copy.deepcopy 深拷贝 拷贝对象及其子对象
一个很好的例子:
a = [ 1 , 2 , 3 , 4 ,
[ ' a ' , ' b ' ]] # 原始对象
b = a # 赋值,传对象的引用
c = copy.copy(a) # 对象拷贝,浅拷贝
d = copy.deepcopy(a) # 对象拷贝,深拷贝
a.append( 5 ) # 修改对象a
a[ 4 ].append( ' c ' ) # 修改对象a中的['a',
'b']数组对象
print ' a
= ' ,
a
print ' b
= ' ,
b
print ' c
= ' ,
c
print ' d
= ' ,
d
输出结果:
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']]
----默认赋值都是传递引用的,如果要获得对象的拷贝,可通过下面的接口-----
Interface summary:
- copy.copy(x)
-
Return a shallow copy of x.
- copy.deepcopy(x)
-
Return a deep copy of x.
对于浅拷贝来说对象本身是新的,内容是旧的。
python的这一特点让我想到了C++的拷贝构造函数与,很久没有注意这块内容,于是反箱倒海找了个网上比较不错的资料以供比较:
以下是C++内容
一. 什么是拷贝构造函数
首先对于普通类型的对象来说,它们之间的复制是很简单的,例如:
int a = 100;
int b = a;
而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。
下面看一个类对象拷贝的简单例子。
- #include <iostream>
- using namespace std;
- class CExample {
- private:
- int a;
- public:
- //构造函数
- CExample(int b)
- { a = b;}
- //一般函数
- void Show ()
- {
- cout<<a<<endl;
- }
- };
- int main()
- {
- CExample A(100);
- CExample B = A; //注意这里的对象初始化要调用拷贝构造函数,而非赋值
- B.Show ();
- return 0;
- }
运行程序,屏幕输出100。从以上代码的运行结果可以看出,系统为对象 B 分配了内存并完成了与对象
A 的复制过程。就类对象而言,相同类型的类对象是通过拷贝构造函数来完成整个复制过程的。
下面举例说明拷贝构造函数的工作过程。
- #include <iostream>
- using namespace std;
- class CExample {
- private:
- int a;
- public:
- //构造函数
- CExample(int b)
- { a = b;}
- //拷贝构造函数
- CExample(const CExample& C)
- {
- a = C.a;
- }
- //一般函数
- void Show ()
- {
- cout<<a<<endl;
- }
- };
- int main()
- {
- CExample A(100);
- CExample B = A; // CExample B(A); 也是一样的
- B.Show ();
- return 0;
- }
CExample(const CExample& C) 就是我们自定义的拷贝构造函数。可见,拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它必须的一个参数是本类型的一个引用变量。
二. 拷贝构造函数的调用时机
在C++中,下面三种对象需要调用拷贝构造函数!
1. 对象以值传递的方式传入函数参数
- class CExample
- {
- private:
- int a;
- public:
- //构造函数
- CExample(int b)
- {
- a = b;
- cout<<"creat: "<<a<<endl;
- }
- //拷贝构造
- CExample(const CExample& C)
- {
- a = C.a;
- cout<<"copy"<<endl;
- }
- //析构函数
- ~CExample()
- {
- cout<< "delete: "<<a<<endl;
- }
- void Show ()
- {
- cout<<a<<endl;
- }
- };
- //全局函数,传入的是对象
- void g_Fun(CExample C)
- {
- cout<<"test"<<endl;
- }
- int main()
- {
- CExample test(1);
- //传入对象
- g_Fun(test);
- return 0;
- }
调用g_Fun()时,会产生以下几个重要步骤:
(1).test对象传入形参时,会先会产生一个临时变量,就叫 C 吧。
(2).然后调用拷贝构造函数把test的值给C。 整个这两个步骤有点像:CExample C(test);
(3).等g_Fun()执行完后, 析构掉 C 对象。
2. 对象以值传递的方式从函数返回
- class CExample
- {
- private:
- int a;
- public:
- //构造函数
- CExample(int b)
- {
- a = b;
- }
- //拷贝构造
- CExample(const CExample& C)
- {
- a = C.a;
- cout<<"copy"<<endl;
- }
- void Show ()
- {
- cout<<a<<endl;
- }
- };
- //全局函数
- CExample g_Fun()
- {
- CExample temp(0);
- return temp;
- }
- int main()
- {
- g_Fun();
- return 0;
- }
当g_Fun()函数执行到return时,会产生以下几个重要步骤:
(1). 先会产生一个临时变量,就叫XXXX吧。
(2). 然后调用拷贝构造函数把temp的值给XXXX。整个这两个步骤有点像:CExample XXXX(temp);
(3). 在函数执行到最后先析构temp局部变量。
(4). 等g_Fun()执行完后再析构掉XXXX对象。
3. 对象需要通过另外一个对象进行初始化