Python中的引用和拷贝浅析

所属分类: 脚本专栏 / python 阅读数: 1878
收藏 0 赞 0 分享

If an object's value can be modified, the object is said to be mutable. If the value cannot be modified,the object is said to be immutable.

mutable 可变类型,例如 list,set,自定义类型(等价于C#中的引用类型);

immutable 不可变类型,例如string,numbers等(等价于C#中的值类型);

一、引用和拷贝(references and copies)

当程序中使用=赋值操作符时,例如a=b,

对于不可变的对象,a作为b的一个拷贝被创建,a和b将指向不同的内存地址,a和b相互独立。

复制代码 代码如下:

def TestCopy():
    a = 10
    b = a
    a =20
    print (b) #b still is 10

但是对于可变的对象,a作为b的一个引用被创建,a和b的元素公用相同的内存地址,a和b的元素共享。
复制代码 代码如下:

def TestRef():
    a=[1,2,3,4]
    b=a   #b is a reference to a
    print (b is a) # True
    b[2] = -100 #change an element in b
    print (a) # a also changed to [1,2,-100,4]

二、深拷贝和浅拷贝(shallow copy and deep copy)

为了避免可变对象指向同一个对象,必须创建一个新的拷贝,而不是引用。
在python中可以对容器对象(例如lists和dictionaries)使用两种拷贝:浅拷贝和深拷贝。
 
浅拷贝创建一个新的对象,但是使用原来对象的元素的引用(如果是不变类型,相当于是拷贝)来填充新对象。可以使用copy.copy()来实现浅拷贝。

复制代码 代码如下:

def TestShallowCopy():
    a = [ 1, 2, [3,4] ]
    b = list(a) # create a shallow copy of a
    print (b is a) #False
    b.append(100) #append element to b
    print (b)
    print (a) # a is unchanged
    b[2][0] = -100 # modify an element inside b
    print (b)
    print (a)  # a is changed

在这个例子中,a和b共享相同的可变元素。所以修改其中一个list对象中的元素,另一个list对象也会被修改。

深拷贝创建一个新的对象,同时递归地拷贝对象所包含的所有的元素。可以使用copy.deepcopy()来实现深拷贝。

复制代码 代码如下:

def TestDeepCopy():
  import copy
  a = [1, 2, [3, 4]]
  b = copy.deepcopy(a)
  b[2][0] = -100
  print (b)  # b is changed
  print (a)  # a is unchanged

在这个例子中,a和b是对立的list对象,且他们的元素也相互独立。

三、引用计数和垃圾回收

python中的所有的对象都是引用计数的,一个对象赋值或加入容器时,它的引用计数就会自增,当使用del时或变量赋值为其他值时,引用计数就会自减,当引用计数为0时,python的垃圾回收器就会回收该变量。

复制代码 代码如下:

def TestGarbageCollection():
  import sys
  print(sys.getrefcount(37))
  a = 37 # Creates an object with value 37
  print(sys.getrefcount(37))
  b = a # Increases reference count on 37
  print(sys.getrefcount(37))
  c = []
  c.append(b) # Increases reference count on 37
  print(sys.getrefcount(37))
  del a # Decrease reference count of 37
  print(sys.getrefcount(37))
  b = 42 # Decrease reference count of 37
  print(sys.getrefcount(37))
  c[0] = 2.0 # Decrease reference count of 37
  print(sys.getrefcount(37))
 
TestGarbageCollection()

运行结果为:

复制代码 代码如下:

11
12
13
14
13
12
11

为啥一上来就有11个引用了呢?谁知道?

更多精彩内容其他人还在看

python2.7无法使用pip的解决方法(安装easy_install)

下面小编就为大家分享一篇python2.7无法使用pip的解决方法(安装easy_install),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Python实现的计算马氏距离算法示例

这篇文章主要介绍了Python实现的计算马氏距离算法,简单说明了马氏距离算法原理,并结合实例形式分析了Python实现与使用马氏距离算法的相关操作技巧,需要的朋友可以参考下
收藏 0 赞 0 分享

python逐行读写txt文件的实例讲解

下面小编就为大家分享一篇python逐行读写txt文件的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

python批量读取txt文件为DataFrame的方法

下面小编就为大家分享一篇python批量读取txt文件为DataFrame的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Python通过调用mysql存储过程实现更新数据功能示例

这篇文章主要介绍了Python通过调用mysql存储过程实现更新数据功能,结合实例形式分析了Python调用mysql存储过程实现更新数据的具体步骤与相关操作技巧,需要的朋友可以参考下
收藏 0 赞 0 分享

Python实现的HMacMD5加密算法示例

这篇文章主要介绍了Python实现的HMacMD5加密算法,简单说明了HMAC-MD5加密算法的概念、原理并结合实例形式分析了Python实现HMAC-MD5加密算法的相关操作技巧,,末尾还附带了Java实现HMAC-MD5加密算法的示例,需要的朋友可以参考下
收藏 0 赞 0 分享

图解Python变量与赋值

Python是一门独特的语言,与C语言有很大区别,初学Python很多萌新表示对变量与赋值不理解,这里就大家介绍一下,需要的朋友可以参考下
收藏 0 赞 0 分享

Python中的并发处理之asyncio包使用的详解

本篇文章主要介绍了Python中的并发处理之asyncio包使用的详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Python获取二维矩阵每列最大值的方法

下面小编就为大家分享一篇Python获取二维矩阵每列最大值的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

numpy找出array中的最大值,最小值实例

下面小编就为大家分享一篇numpy找出array中的最大值,最小值实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享
查看更多