深拷貝:賦值時值徹底複製,徹底的copy,對其中一個做出改變,不會影響另外一個php
淺拷貝:賦值時,引用賦值,至關於取了一個別名。對其中一個修改,會影響另外一個html
對於PHP而言,= 賦值時,普通對象是深拷貝,但對對象來講,是淺拷貝,即引用賦值。當對象做爲參數傳遞時,不管參數前是否有&引用符號,都將被看作是賦值引用。python
對於python而言,狀況可能會有點小複雜,由於python一切皆爲對象,因此python的普通賦值、深拷貝和淺拷貝之間都是有細微區別的。編程
在php5中,對象的 = 賦值和傳遞都是引用。要想實現拷貝副本,php提供了clone函數實現。clone徹底copy了一份副本。可是clone時,咱們可能不但願copy源對象的全部內容,那咱們能夠利用__clone來操做。
請看以下代碼段:函數
<?php //普通對象賦值,深拷貝,徹底值複製 $m = 1; $n = $m; $n = 2; echo $m;//值複製,對新對象的改變不會對m做出改變,輸出 1.深拷貝 echo PHP_EOL; /*==================*/ //對象賦值,淺拷貝,引用賦值 class Test{ public $a=1; } $m = new Test(); $n = $m;//引用賦值 $m->a = 2;//修改m,n也隨之改變 echo $n->a;//輸出2,淺拷貝 echo PHP_EOL; ?>
因爲對象的賦值時引用,要想實現值複製,php提供了clone函數來實現複製對象。可是clone函數存在這麼一個問題,克隆對象時,原對象的普通屬性能值複製,可是源對象的對象屬性賦值時仍是引用賦值,淺拷貝。性能
<?php class Test{ public $a=1; } class TestOne{ public $b=1; public $obj; //包含了一個對象屬性,clone時,它會是淺拷貝 public function __construct(){ $this->obj = new Test(); } } $m = new TestOne(); $n = $m;//這是徹底的淺拷貝,不管普通屬性仍是對象屬性 $p = clone $m; //普通屬性實現了深拷貝,改變普通屬性b,不會對源對象有影響 $p->b = 2; echo $m->b;//輸出原來的1 echo PHP_EOL; //對象屬性是淺拷貝,改變對象屬性中的a,源對象m中的對象屬性中a也改變 $p->obj->a = 3; echo $m->obj->a;//輸出3,隨新對象改變 ?>
要想實現對象真正的深拷貝,有如下兩種方法:this
一、利用序列化反序列化實現spa
<?php class Test{ public $a=1; } class TestOne{ public $b=1; public $obj; //包含了一個對象屬性,clone時,它會是淺拷貝 public function __construct(){ $this->obj = new Test(); } } $m = new TestOne(); //方法二,序列化反序列化實現對象深拷貝 $n = serialize($m); $n = unserialize($n); $n->b = 2; echo $m->b;//輸出原來的1 echo PHP_EOL; //能夠看到,普通屬性實現了深拷貝,改變普通屬性b,不會對源對象有影響 $n->obj->a = 3; echo $m->obj->a;//輸出1,不隨新對象改變,仍是保持了原來的屬性,能夠看到,序列化和反序列化能夠實現對象的深拷貝 ?>
二、寫clone函數.net
<?php class Test{ public $a=1; } class TestOne{ public $b=1; public $obj; //包含了一個對象屬性,clone時,它會是淺拷貝 public function __construct(){ $this->obj = new Test(); } //方法一:重寫clone函數 public function __clone(){ $this->obj = clone $this->obj; } } $m = new TestOne(); $n = clone $m; $n->b = 2; echo $m->b;//輸出原來的1 echo PHP_EOL; //能夠看到,普通屬性實現了深拷貝,改變普通屬性b,不會對源對象有影響 //因爲改寫了clone函數,如今對象屬性也實現了真正的深拷貝,對新對象的改變,不會影響源對象 $n->obj->a = 3; echo $m->obj->a;//輸出1,不隨新對象改變,仍是保持了原來的屬性 ?>
「對一個對象進行淺拷貝實際上是新建立了一個類型和原來對象同樣,可是內容是原來對象元素的引用。換句話說,這個拷貝的對象自己是新的,可是它的內容不是」,摘自《Python核心編程》。code
這是我我的對python下淺拷貝和深拷貝的理解:
賦值:簡單地拷貝對象的引用,兩個對象的id相同。
淺拷貝:建立一個新的組合對象,這個新對象與原對象共享內存中的子對象。
深拷貝:建立一個新的組合對象,同時遞歸地拷貝全部子對象,新的組合對象與原對象沒有任何關聯。雖然實際上會共享不可變的子對象,但不影響它們的相互獨立性。
淺拷貝和深拷貝的不一樣僅僅是對組合對象來講,所謂的組合對象就是包含了其它對象的可變對象,如列表,類實例。而對於數字、字符串以及其它「原子」類型,沒有拷貝一說,產生的都是原對象的引用。
下面的代碼但願能對你有進一步的幫助;
#! /usr/bin/python # -*- coding:UTF-8 -*- import copy # 淺拷貝 a = [1, "a", 3, [4, 5, 6], [[7, 8, 9]]] b = a c = list(a) d = copy.deepcopy(a) print "原地址&&&" print id(a) print "賦值地址&&&" print id(b) print "淺拷貝地址&&&" print id(c) print "深拷貝地址&&&" print id(d) print "賦值地址###" for i, j in zip(a, b): print id(i), id(j) print "淺拷貝地址###" for i, j in zip(a, c): print id(i), id(j) print "深拷貝地址###" for i, j in zip(a, d): print id(i), id(j) print "######" a[0] = 2 a[3][0] = 14 print "原值變化爲 %d, %d" % (a[0], a[3][0]) print "*******" print "賦值變化" print b[0], b[3][0] print "淺拷貝變化" print c[0], c[3][0] print "深拷貝變化" print d[0], d[3][0] print "**##$$" print a
輸出以下:
http://www.cnblogs.com/taijun...
http://blog.csdn.net/u0115085...
http://www.cnblogs.com/zxlove...