從C C++的角度看PYTHON的深淺拷貝
原創如果有誤請指出
今天看到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沒有更改。那麼我們用記憶體四區圖來描述
圖中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中的很多現象很好理解。
作者微信:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2144168/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- C++淺拷貝和深拷貝C++
- 【c++】淺拷貝與深拷貝C++
- C++拷貝建構函式(深拷貝,淺拷貝)C++函式
- Objective C淺拷貝和深拷貝Object
- Python淺拷貝與深拷貝Python
- python深拷貝與淺拷貝Python
- python深淺拷貝Python
- 深淺拷貝 pythonPython
- python 指標拷貝,淺拷貝和深拷貝Python指標
- js的深拷貝和淺拷貝JS
- 物件的深拷貝與淺拷貝物件
- 深入淺出的“深拷貝與淺拷貝”
- 淺談深拷貝與淺拷貝?深拷貝幾種方法。
- vue深拷貝淺拷貝Vue
- 圖解 Python 淺拷貝與深拷貝圖解Python
- Python中列表的深淺拷貝Python
- JavaScript中的淺拷貝與深拷貝JavaScript
- VUE 中 的深拷貝和淺拷貝Vue
- 對淺拷貝和深拷貝的理解
- 淺拷貝與深拷貝的實現
- 【JavaScript】物件的淺拷貝與深拷貝JavaScript物件
- 淺談Java中的淺拷貝和深拷貝Java
- java深克隆(深拷貝)和淺克隆(淺拷貝)Java
- Python - 物件賦值、淺拷貝、深拷貝的區別Python物件賦值
- 【JS】深拷貝與淺拷貝,實現深拷貝的幾種方法JS
- Python3之淺談----深拷貝與淺拷貝Python
- 【Python】直接賦值,深拷貝和淺拷貝Python賦值
- Python擴充套件_淺拷貝和深拷貝Python套件
- iOS深拷貝和淺拷貝iOS
- JS深拷貝與淺拷貝JS
- Java深拷貝和淺拷貝Java
- 物件深拷貝和淺拷貝物件
- javascript 淺拷貝VS深拷貝JavaScript
- JavaScript深拷貝和淺拷貝JavaScript
- js 淺拷貝和深拷貝JS
- js 深拷貝和淺拷貝JS
- JavaScript淺拷貝和深拷貝JavaScript
- js深拷貝和淺拷貝JS