python 浅拷贝与深拷贝

python变量在内存中是这样存储的:

在python中,一切都是对象,对象的存储是引用存储,存储的只是变量的值所在的内存地址,而不是这个变量的值本身。

如果对值进行修改,其实是在内存中新创建一个值,把变量指向这个值的地址

可以看出地址发生了改变

如果是两个值相等,那么改变其中一个不会影响另一个

a=b时a,b指向同一个地址

改变a的值后b不会改变

说明是在内存中新创建了一个值,a指向了这个值的地址

这是基本类型的存储

python中可以分两大类数据类型,一种是基础数据类型,如 int str float,long ,bool等基础类型,另一种是list,tulpe,dict,set等复杂类型,list,tulpe,dict,set中包含基础类型

由于python中的变量都是采用的引用存储,而list,tuple,dict这种数据结构可以包含基础数据类型,这就导致了每个变量中都存储了这个变量的地址,而不是值本身;对于复杂的数据结构来说,里面的存储的也只是每个元素的地址而已。

如果是list列表的存储形式:

L = [1,2,3,'a','b','c']

print(id(L))

变量L的地址为

每个元素的地址为

L = [1,2,3,'a','b','c']

#print(id(L))

print(id(L[0]))

print(id(L[1]))

print(id(L[2]))

print(id(L[3]))

print(id(L[4]))

L所存的就是这些元素的地址

在内存表现形式为:

将列表L的内容赋值给另一个变量和字符的操作一样

L = [1,2,3,'a','b','c']

Y = L

print(L)

print(Y)

print(id(L))

print(id(Y))

对L追加元素:

L = [1,2,3,'a','b','c']

Y = L

print(L)

print(Y)

print(id(L))

print(id(Y))

L.append("f")

print(L)

print(Y)

print(id(L))

print(id(Y))

如果重新赋值或者说重新初始化,那么会重新分配新的内存空间

L = [1,2,3,'a','b','c']

Y = L

print(L)

print(Y)

print(id(L))

print(id(Y))

L.append("f")

print(L)

print(Y)

print(id(L))

print(id(Y))

L = ['a','b','c']

print(L)

print(Y)

print(id(L))

print(id(Y))

也就是说如果在地址上操作那么指向这两个地址的变量的内容都会改变但是地址指向不变

如果重新赋值,那么重新赋值的那个变量地址就会指向新的内存地址

这就是变量赋值的过程

浅拷贝

浅拷贝:不管多么复杂的数据结构,浅拷贝都只会copy一层。

基础数据的拷贝,不管浅拷贝还是深拷贝都一样都会重新分配内存地址

#基础数据拷贝

import copy

L = [1,2,3,'a','b']

M = copy.copy(L)

print(L)

print(M)

print(id(L))

print(id(M))

import copy

L = [1,2,3,'a','b']

M = copy.copy(L)

print(L)

print(M)

print(id(L))

print(id(M))

#给L追加一个元素M不会变

L.append("c")

print(L)

print(M)

print(id(L))

print(id(M))

深拷贝基础数据:

import copy

L = [1,2,3,'a','b']

M = copy.deepcopy(L)

print(L)

print(M)

print(id(L))

print(id(M))

#给L追加一个元素M不会变

L.append("c")

print(L)

print(M)

print(id(L))

print(id(M))

结果和浅拷贝一样

复杂的数据:

仅仅对外层修改拷贝后L改变M不变

import copy

L = [1,2,[3,4,'c','d'],'a','b']

M = copy.copy(L)

print(L)

print(M)

print(id(L))

print(id(M))

#给L追加一个元素M不会变

L.append("c")

print(L)

print(M)

print(id(L))

print(id(M))

对内层改变,那么拷贝后都会变

import copy

L = [1,2,[3,4,'c','d'],'a','b']

M = copy.copy(L)

print(L)

print(M)

print(id(L))

print(id(M))

L[2].append("e")

print(L)

print(M)

print(id(L))

print(id(M))

这说明对内层数据的修改会改变另一个拷贝的对象

在内存中的形式为:

上图可以看出,内层list[1,2]也是一个地址,里面存的就是元素1,2的地址

所以对L的内层操作就是对内层list[1,2]地址的操作,这样就会改变M

深度拷贝:

import copy

L = [1,2,[3,4,'c','d'],'a','b']

M = copy.deepcopy(L)

print(L)

print(M)

print(id(L))

print(id(M))

#给L追加一个元素M不会变

L[2].append("e")

print(L)

print(M)

print(id(L))

print(id(M))

可以看出L改变M不变

在内存中的形式:

相当于所有的都拷贝一份

1、对于复杂的数据结构copy.copy 浅拷贝 只拷贝父对象(最外一层),不会拷贝对象的内部(内层数据)的子对象。

2、copy.deepcopy 深拷贝 拷贝父对象(外层数据)及其子对象(内层数据)

3、对于基本数据类型深拷贝浅拷贝都一样,都会产生新的数据空间

原文地址:http://blog.51cto.com/linuxubuntu/2087773

时间: 2024-10-29 00:48:07

python 浅拷贝与深拷贝的相关文章

Python 浅拷贝和深拷贝

一.前奏:熟悉Python内存管理 在Python中,变量在第一次赋值时自动声明,在创建---也就是赋值的时候,解释器会根据语法和右侧的操作数来决定新对象的类型. 引用计数器:一个内部跟踪变量 引用计数:每一个对象各有多少个引用 当对象被创建并(将其引用)赋值给变量时,该对象的引用计数就被设置为 1 >>> x = 3.14 语句 x=3.14,创建一个浮点型对象并将其引用赋值给了x,x是第一个引用,该对象的引用计数为1 当一个对象(的引用)又被赋值到其他变量,或做参数传递等,该对象的一

python浅拷贝和深拷贝

今天写兑换码时,玩家兑换兑换码时,拿到了上个兑换码的奖励,还一直怀疑,mysql取该兑换码那个环节出错了,实际上是直接引用了全局常量里的数据.导致后面全局常量的数据用的是上个兑换码的奖励内容. 今天就来说说前拷贝和深拷贝之分吧! 浅拷贝: copy.copy:拷贝内容 浅拷贝会生成一个新的对象,但是还是会使用原始数据的引用(地址),对可变类型操作会使用一个新的对象, 对不可变类型操作不会产生新的对象(list,dict,),并修改对应的值. 深拷贝: copy.deepcopy:完全拷贝内容 深

Python之美[从菜鸟到高手]--浅拷贝、深拷贝完全解读(copy源码分析)

可悲的我一直以为copy模块是用C写的,有时候需要深入了解deepcopy,文档描述的实在太简单,还是不知所云. 比如说最近看sqlmap源码中AttribDict的_deepcopy__有些疑惑, def __deepcopy__(self, memo): retVal = self.__class__() memo[id(self)] = retVal for attr in dir(self): if not attr.startswith('_'): value = getattr(se

python中关于赋值、浅拷贝与深拷贝的问题

Python中关于对象复制有三种类型的使用方式,赋值.浅拷贝与深拷贝.他们既有区别又有联系,刚好最近碰到这一类的问题,研究下. 一.赋值 在python中,对象的赋值就是简单的对象引用,这点和C++不同.如下: list_a = [1,2,3,"hello",["python","C++"]] list_b = list_a 这种情况下,list_b和list_a是一样的,他们指向同一片内存,list_b不过是list_a的别名,是引用. 我们可

一入python深似海--浅拷贝与深拷贝

python中有一个模块copy,deepcopy函数用于深拷贝,copy函数用于浅拷贝.要理解浅拷贝,必须先弄清楚python中的引用. 引用 Python中一切都是对象,变量中存放的是对象的引用.这是一个普遍的法则.可以说 Python 没有赋值,只有引用.如,a=1,变量a只是整数对象1的引用. 可变对象与不可变对象及其引用 一.不可变对象 不可变对象包括:数字,字符串,元组. 由于Python中的变量存放的是对象引用,所以对于不可变对象而言,尽管对象本身不可变,但变量的对象引用是可变的.

Python中赋值、浅拷贝与深拷贝

python中关于对象复制有三种类型的使用方式,赋值.浅拷贝与深拷贝.他们既有区别又有联系,刚好最近碰到这一类的问题,研究下. 一.赋值 在python中,对象的赋值就是简单的对象引用,这点和C++不同.如下: list_a = [1,2,3,"hello",["python","C++"]] list_b = list_a 这种情况下,list_b和list_a是一样的,他们指向同一片内存,list_b不过是list_a的别名,是引用. 我们可

Python中的赋值、浅拷贝、深拷贝

在理解浅拷贝和深拷贝之前,首先要理解学习一下变量在Python中是怎样存储的: 变量的类型是分值引用与地址引用两种. python的一切变量都是对象,变量的存储,采用了地址引用的方式,存储的只是一个变量的值所在的内存地址,而不是这个变量的只本身. 在Python中,是有多种数据类型:bool.int.long.float.string.list.dict.tuple.set; 其中可分为基本数据类型和复杂数据结构: 基本数据类型:bool.int.long.float.string; 复杂数据结

python中的深拷贝和浅拷贝理解

在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用.以下分两个思路来分别理解浅拷贝和深拷贝: 利用切片操作和工厂方法list方法拷贝 利用copy中的deepcopy方法进行拷贝 1.利用切片操作和工厂方法list方法拷贝 代码场景:有一个小伙jack,tom通过切片操作拷贝jack,anny通过工厂方法拷贝jack. >>> jack = ['jack', ['age', 20]] &g

Python(2.7.6) copy 浅拷贝与深拷贝

Python 标准库的 copy 模块提供了对象拷贝的功能. copy 模块中有两个函数 copy 和 deepcopy,分别支持浅拷贝与深拷贝. copy_demo.py import copy class MyClass(object): def __init__(self, name): super(MyClass, self).__init__() self.name = name a = [MyClass('huey')] b = copy.copy(a) c = copy.deepc