Python中对象的引用与复制
在python进行像b = a这样的赋值时,只会创建一个对a的新引用,使a的引用计数加1,而不会创建新的对象:
>>> a = 'xyz'
>>> import sys
>>> sys.getrefcount(a)
3
>>> b = a
>>> sys.getrefcount(b)
4
>>> id(a)
88292288L
>>> id(b)
88292288L
这样,当引用的对象是可变对象的时候(列表,字典,可变集合等),会产生意料之外的行为:
>>> a = [1, 2, 3, 4]
>>> b = a
>>> b.append(5)
>>> a
[1, 2, 3, 4, 5]
因为a和b引用的是同一对象,改变其中一个,另外一个也会随之改变。当我们想建立一个副本而不是引用时,可以复制对象。
复制对象一般使用copy模块:
>>> a = [1, 2, 3, 4]
>>> import copy
>>> b = copy.copy(a)
>>> b.append(5)
>>> b
[1, 2, 3, 4, 5]
>>> a
[1, 2, 3, 4]
这样就可以了,但这种复制是一种浅复制,复制的新对象中包含的是对原始对象中的项的引用,如果对象的项为可变对象,也会产生不可控行为:
>>> a = [1, [1, 2]]
>>> b = copy.copy(a)
>>> b[1].append(3)
>>> b
[1, [1, 2, 3]]
>>> a
[1, [1, 2, 3]]
这时候就要使用深复制了。深复制将创建一个新对象,并递归地复制它所包含的所有对象:
>>> a = [1, [1, 2]]
>>> b = copy.deepcopy(a)
>>> b[1].append(3)
>>> b
[1, [1, 2, 3]]
>>> a
[1, [1, 2]]
对于不可改变的对象而言(字符串,数字,元组)等,没有必要拷贝,因为它们是不可改变的,不用担心会不经意间改动了它们。拷贝操作也只会得到原对象:
>>> a = (1, 2, 3)
>>> b = copy.copy(a)
>>> a is b
True
对于可变对象来(列表,字典,可变集合)来说,可以分别使用内置函数list(),dict(),set()来进行浅复制,速度是比使用copy模块快的。
列表也可以使用切片进行浅复制:
>>> a = [1, 2, 3, 4]
>>> b = a[:]
>>> a is b
False
>>> b
[1, 2, 3, 4]
对序列数据类型(字符串,列表,元组)进行*操作时,也仅仅是复制了对象中项的引用,如果使用*创建一个多维列表:
>>> a = [1, 2, 3]
>>> b = [a]
>>> c = b * 3
>>> a.append(4)
>>> c
[[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]
最好是在列表推导中使用浅复制来创建多维列表,可以避免隐式的引用共享:
>>> a = [1, 2, 3]
>>> c = [list(a) for i in range(3)]
>>> a.append(4)
>>> c
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
Python中对象的引用与复制的更多相关文章
- Python中的变量引用对象需注意的几点
Python中的变量引用对象需注意的几点 分类:Python (55) (0) 普通引用: Python中,变量的作用仅仅是一个标识,只有赋值后才被创建,它可以引用任何类型的对象,而且在引用之前必须 ...
- 【Python】Python中对象管理与垃圾回收中两个很有意思的问题
再Python中是利用引用计数来实现对象管理和垃圾回收的,即其他对象引用该对象时候,其引用计数加1,反之减1,当引用计数为0时候,被垃圾收集器回收. Python解释器对对象以及计数器的管理分为以下两 ...
- Java中对象与引用
初学Java 时.在非常长一段时间里,总认为基本概念非常模糊. 后来才知道.在很多Java 书中.把对象和对象的引用混为一谈. 假设分不清对象与对象引用,那实在没法非常好地理解以下的面向对象技术.把自 ...
- Java中对象和引用的理解
偶然想起Java中对象和引用的基本概念,为了加深下对此的理解和认识,特地整理一下相关的知识点,通过具体实例从两者的概念和区别两方面去更形象的认识理解,再去记忆. 一.对象和引用的概念: 在Java中万 ...
- 深入理解python(一)python语法总结:基础知识和对python中对象的理解
用python也用了两年了,趁这次疫情想好好整理下. 大概想法是先对python一些知识点进行总结,之后就是根据python内核源码来对python的实现方式进行学习,不会阅读整个源码,,,但是应该会 ...
- python中对象、类型和元类之间的关系
在python中对象.类型和元类构成了一个微妙的世界. 他们有在这个世界里和平共处,相辅相成.它们遵循着几条亘古不变的定律: 1.python中无处不对象 2.所有对象都有三种特性:id.类型.值 3 ...
- 谈谈Python中对象拷贝
你想复制一个对象?因为在Python中,无论你把对象做为参数传递,做为函数返回值,都是引用传递的. 何谓引用传递,我们来看一个C++交换两个数的函数: void swap(int &a, in ...
- python中的变量引用小结
python的变量都可以看成是内存中某个对象的引用.(变量指向该内存地址存储的值) 1.python中的可更改对象和不可更改对象 python中的对象可以分为可更改(mutable)对象与不可更改(i ...
- python中的赋值操作和复制操作
之前一直写C#,变量之间赋值相当于拷贝,修改拷贝变量不会改变原来的值.但是在python中发现赋值操作本质是和C++中的引用类似,即指向同一块内存空间.下面通过一个例子说明: p=[0,1,2,3,4 ...
随机推荐
- HP-UX平台Oracle启动实例遭遇:ORA-27154,ORA-27300,ORA-27301,ORA-27302
环境:HP-UX 11.31 + Oracle 11.2.0.4 现象:在hpux安装Oracle,按业务需求配置参数后,无法启动实例. 报错如下: ORA-27154:post/wait creat ...
- sqli-labs(十六)(order by注入)
第四十六关: http://www.bubuko.com/infodetail-2481914.html 这有篇文章讲得还不错可以看下 这关是order by后面的一个注入,用报错注入和盲注都是可以的 ...
- mysql制造大量测试数据心得
为了测试1000万条数据的查询性能,就需要1000万条数据,于是在我们做的项目的一个游客表的一条记录的基础上来制造. 1.使用mysql的while循环语句,比如手机号的循环,还有一些随机数,比如性别 ...
- Python之描述器
1.描述器的表现 用到三个魔术方法,__get__(), __set__(), __delete__() 方法签名如下 object.__get__(self,instance,owner) obje ...
- 大数据处理框架之Strom:认识storm
Storm是分布式实时计算系统,用于数据的实时分析.持续计算,分布式RPC等. (备注:5种常见的大数据处理框架:· 仅批处理框架:Apache Hadoop:· 仅流处理框架:Apache Stor ...
- 设计模式之Factory(工厂)(转)
定义:提供创建对象的接口. 为何使用? 工厂模式是我们最常用的模式了,著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见. 为什么工厂模式是如此常用?因为工厂模式就 ...
- 转:C#清除回收站
SHEmptyRecycleBin是一个内核API方法,该方法能够清空回收站中的文件,该方法在C#中需要手动的引入方法所在的类库.该方法在C#中的声明语法如下: [DllImportAttrbute( ...
- JustOj 1032: 习题6.7 完数
题目描述 一个数如果恰好等于它的因子之和,这个数就称为"完数". 例如,6的因子为1.2.3,而6=1+2+3,因此6是"完数". 编程序找出N之内的所有完数, ...
- <转>jmeter(十)参数化
本博客转载自:http://www.cnblogs.com/imyalost/category/846346.html 个人感觉不错,对jmeter讲解非常详细,担心以后找不到了,所以转发出来,留着慢 ...
- jdbc --例子7
package cn.kitty.o1; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLE ...