今天看到Python的列表深浅拷贝,不由得和C\C++进行了比较如下:
其实python中的深COPY和浅COPY和C\C++中是一样的,毕竟python底层是C/C++做的,这方面保留了
C\C++的原理,对于类或者结构体复制构造函数等号(=)操作符保留了浅COPY,当然我们可以自定义
这些函数。我们先从C++的简单的复制构造函数等号(=)操作符的例子开始
#include<iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;
class testcy
{
private:
char* a;
unsigned int b;
public:
testcy(const char* inc)
{
a = new char[strlen(inc)+1];
strcpy(a,inc);
b = 1;
}
testcy()
{
a= NULL;
b = 0;
}
testcy(const testcy &in) //浅copy 构造函数
{
this->a = in.a;
this->b = in.b;
}
testcy& operator=(const testcy& in)//浅=值操作符重载
{
this->a = in.a;
this->b = in.b;
}
void print()
{
cout<<this->a<<" ";
cout<<this->b<<endl;
}
void modify(const char* in,const int in2)
{
if(strlen(a) < strlen(in))
{
cout<< "error:much lenth than point a char"<<endl;
exit(1);
}
else
{
for(int i=0;i<strlen(in);i++)
{
*(a+i) = *(in+i);
}
}
b = in2;
}
};
int main(void)
{
testcy a("123123");
testcy b = a;
testcy c ;
c = a;
cout<<"source data:"<<endl;
cout<<"string int"<<endl;
a.print();
b.print();
c.print();
cout<<"after only change a:"<<endl;
cout<<"string int"<<endl;
a.modify("asd",2);
a.print();
b.print();
c.print();
}
非常简单就是为了演示浅COPY输出如下:
source data:
string int
123123 1
123123 1
123123 1
after only change a:
string int
asd123 2
asd123 1
asd123 1
我们可以看到在修改a的数据后b、c的数据string数据也更改了,但是简单类型int没有更改。那么我们用内存四区图来描述
123.jpg
图中a->a当然就是整形,但是a->b是指针其指针的值0XB0120存在栈中但是实际指向的数据存在堆中,
而变量b->b,c->b指向了同一块内存 导致一改全部都改了,但是a->a,b->a,c->a确实单独的在栈上了的
没影响。其实这里我们只要修改浅COPY为深COPY改变其实现即可比如
testcy(const testcy &in) //深copy 构造函数
{
this->a = new char[strlen(in.a)+1];
strcpy(this->a,in.a);
this->b = in.b;
}
我们要做的不仅仅是要指针相等而是要将内存重新分配。注意本测试程序没有写析构函数。
下面我们来看看python的浅列表拷贝
import copy
a = ['t1','t2','t3','t4']
b = a
print("source data")
print(a);
print(b);
a[0] = 'gao'
print("after change:")
print(a);
print(b);
source data
['t1', 't2', 't3', 't4']
['t1', 't2', 't3', 't4']
after change:
['gao', 't2', 't3', 't4']
['gao', 't2', 't3', 't4']
确实如此,修改了列表元素a[0]的值b列表也修改了,我们有了C++的那张图这个就很好理解了,他们是
指向同一块内存堆区。我们应该使用
a = ['t1','t2','t3','t4']
b = copy.deepcopy(a)
从这个方法的命名我们也可以看到这是深copy,其原理已经在C++代码进行了剖析
另外如下:
a = [['t1','t10'],'t2','t3','t4']
b = a.copy()
print("source data")
print(a);
print(b);
a[0][0] = 'gao'
print("after change:")
print(a);
print(b);
source data
[['t1', 't10'], 't2', 't3', 't4']
[['t1', 't10'], 't2', 't3', 't4']
after change:
[['gao', 't10'], 't2', 't3', 't4']
[['gao', 't10'], 't2', 't3', 't4']
a.copy()只是对第一层进行copy,第二层在python里面实现应该也是指针或者引用,一样的会出问题。
所以copy的时候我们尽量使用copy.deepcopy(a)来得到正确的数据当然根据实际需求定。
可以看到C/C++是理论基础,有了这些理论PYTHON中的很多现象很好理解。