Python赋值、浅拷贝与深拷贝机制解析
本文详细解析Python中对象赋值、浅拷贝与深拷贝的核心机制。通过id()函数验证内存地址,阐明直接赋值仅传递引用;浅拷贝创建新容器但共享子对象引用;深拷贝则完全独立复制父对象及子对象。掌握三者区别可有效避免数据意外修改,提升代码安全性。
在Python中,将对象赋值给变量,实质上是让该变量成为指向内存中存储值的引用。当把一个对象赋值给另一个变量时,新变量并未复制对象本身,而是复制了该对象的引用指针。
通常可以通过三种方式来处理对象的引用关系。
Python直接赋值
直接赋值默认执行的是浅拷贝操作,传递的是对象的引用。原始列表若发生改变,被赋值的变量也会同步发生相同的变化。这本质上是对“对象”引用的传递。
示例:
>>> list_demo = [2, 4, 6]
>>> a = list_demo
>>> print(a)
[2, 4, 6]
>>> id(list_demo)
65006808
>>> id(a)
65006808
>>> list_demo.append(8)
>>> print(list_demo)
[2, 4, 6, 8]
>>> print(a)
[2, 4, 6, 8]
>>> id(list_demo)
65006808
>>> id(a)
65006808
>>>
利用id()函数可以验证,变量list_demo与a指向的是同一个内存空间地址。当被赋值的list_demo发生变化时,被赋值的a也会随之发生相同的改变。这种现象在Python中十分普遍,这种赋值方式实现了“假装”拷贝,实际上两个变量依然指向同一个对象。
Python浅拷贝
通过import copy模块调用copy.copy()方法,该方法仅拷贝父对象,而不拷贝子对象。浅拷贝会创建一块新的内存空间,但新空间内元素的地址均拷贝自父对象元素的地址。因此,当父对象内部的子对象发生改变时,拷贝对象内部的子对象也会随之改变。
示例:
>>> list_demo1 = [2, 4, 6, [8, 10]]
>>> a = list_demo1
>>> print(list_demo1)
[2, 4, 6, [8, 10]]
>>> print(a)
[2, 4, 6, [8, 10]]
>>>
>>>
>>> import copy
>>> b = copy.copy(list_demo1)
>>> id(list_demo1)
65103472
>>> id(b)
6011200
>>> list_demo1.append(12)
>>> print(list_demo1)
[2, 4, 6, [8, 10], 12]
>>> list_demo1[3]
[8, 10]
>>>
>>>
>>>
>>> list_demo1[3].append('hello')
>>> print(list_demo1)
[2, 4, 6, [8, 10, 'hello'], 12]
>>> print(b)
[2, 4, 6, [8, 10, 'hello']]
>>> list_demo1[3]
[8, 10, 'hello']
>>> b[3]
[8, 10, 'hello']
>>>
>>>
>>>
>>> id(list_demo1)
65103472
>>> id(b)
6011200
>>> id(list_demo1[3])
64679128
>>> id(b[3])
64679128
>>>
从上述代码可以看出,执行浅拷贝时,实际上只拷贝了引用而未拷贝内容。同时,浅拷贝会针对父对象的子对象进行判断,当父对象的子对象发生改变时,拷贝对象内的子对象也会同步改变。
Python深拷贝
通过import copy模块调用copy.deepcopy()方法,深拷贝与浅拷贝相反,它进行彻底且完全的拷贝,同时拷贝父对象及子对象,并指向一个新的内存空间地址。此时,尽管源对象与拷贝对象的内容相同,但无论对谁进行修改,另一个对象均不受任何影响。
>>> list_demo2 = [2,3,4]
>>> c= copy.deepcopy(list_demo2)
>>> print(list_demo2)
[2, 3, 4]
>>> print(c)
[2, 3, 4]
>>> id(list_demo2)
6011440
>>> id(c)
6012440
>>> list_demo2.append(['a','b'])
>>> c.append([5,6])
>>> print(list_demo2)
[2, 3, 4, ['a', 'b']]
>>> print(c)
[2, 3, 4, [5, 6]]
>>> list_demo2[3].append('c')
>>> c[3].append(7)
>>> print(list_demo2)
[2, 3, 4, ['a', 'b', 'c']]
>>> print(c)
[2, 3, 4, [5, 6, 7]]
>>>
从上述代码示例可以看出list_demo2与c相互独立,无论list_demo2与c本身进行了修改,或者各自的子对象进行了修改都没有互相影响。
总结
Python赋值
赋值的本质就是将一个对象的内存空间地址赋值给一个变量,让变量指向该内存空间地址。
Python浅拷贝
浅拷贝是拷贝了源对象的引用,并创建了一个新的内存空间地址。但是引用的对象的子对象的地址仍然是源对象的,所以当源对象的子对象发生改变时,拷贝对象内的子对象同时也跟着改变。
Python深拷贝
深拷贝就是彻底的拷贝,完全的拷贝了父对象及子对象,同时指向一个新的内存空间地址。源对象与拷贝对象之间的修改互不影响。
更多关于Python的赋值、深拷贝与浅拷贝的区别文章请查看下面的相关链接
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









