python引用和对象详解
python引用和对象详解
@[马克飞象]
python中变量名和对象是分离的
例子 1:
a = 1
这是一个简单的赋值语句,整数 1 为一个对象,a 是一个引用,利用赋值语句,引用a指向了对象1.
例子 2:
>>> a = 1
>>> id(a)
24834392
>>> a = 'banana'
>>> id(a)
139990659655312
第一个语句中, 2是储存在内存中的一个整数对象,通过赋值 引用a 指向了 对象 1
第二个语句中,内存中建立了一个字符串对象‘banana’,通过赋值 将 引用a 指向了 ‘banana’,同时,对象1不在有引用指向它,它会被python的内存处理机制给当我垃圾回收,释放内存。
例子 3:
>>> a = 3
>>> b = 3
>>> id(a)
10289448
>>> id(b)
10289448
在这里可以看到 这俩个引用 指向了同一个 对象,这是为什么呢? 这个跟python的内存机制有关系,因为对于语言来说,频繁的进行对象的销毁和建立,特别浪费性能。所以在Python中,整数和短小的字符,Python都会缓存这些对象,以便重复使用。
例子 4:
>>> a = 4
>>> b = a
>>> id(a)
36151568
>>> id(b)
36151568
>>> a = a+2
>>> id(a)
36151520
>>> id(b)
36151568
可以看到 a 的引用改变了,但是 b 的引用未发生改变;a,b指向不同的对象; 第3句对 a 进行了重新赋值,让它指向了新的 对象6;即使是多个引用指向同一个对象,如果一个引用值发生变化,那么实际上是让这个引用指向一个新的引用,并不影响其他的引用的指向。从效果上看,就是各个引用各自独立,互不影响。
例子 5:
>>> L1 = [1,2,3]
>>> L2 = L1
>>> id(L1)
139643051219496
>>> id(L2)
139643051219496
>>> L1[0] = 10
>>> id(L1)
139643051219496
>>> id(L2)
139643051219496
>>> L2
[10, 2, 3]
同样的跟第四个例子那样,修改了其中一个对象的值,但是可以发现 结果 并不与 第四个栗子那样, 在本次实验中,L1 和 L2 的引用没有发生任何变化,但是 列表对象[1,2,3] 的值 变成了 [10,2,3](列表对象改变了)
在该情况下,我们不再对L1这一引用赋值,而是对L1所指向的表的元素赋值。结果是,L2也同时发生变化。
原因何在呢?因为L1,L2的指向没有发生变化,依然指向那个表。表实际上是包含了多个引用的对象(每个引用是一个元素,比如L1[0],L1[1]..., 每个引用指向一个对象,比如1,2,3), 。而L1[0] = 10这一赋值操作,并不是改变L1的指向,而是对L1[0], 也就是表对象的一部份(一个元素),进行操作,所以所有指向该对象的引用都受到影响。
(与之形成对比的是,我们之前的赋值操作都没有对对象自身发生作用,只是改变引用指向。)
列表可以通过引用其元素,改变对象自身(in-place change)。这种对象类型,称为可变数据对象(mutable object),词典也是这样的数据类型。
而像之前的数字和字符串,不能改变对象本身,只能改变引用的指向,称为不可变数据对象(immutable object)。
我们之前学的元组(tuple),尽管可以调用引用元素,但不可以赋值,因此不能改变对象自身,所以也算是immutable object.
例子 6:
l = [1,2,3]
for item in l:
item = 8
# 这里只是让item指向l[i]所指向的对象,item = 8,则item指向新的对象8,不改变l[i]
print(l) # [1,2,3]
for i in range(len(l)):
l[i] = 8
# 这里令l[i]指向新的对象 8
print(l) # [8,8,8]
例子 7:
l1 = []
a = 0
for i in range(1,5):
a = i
l1.append(a) # 添加的是a指向的对象
print(l1) # [1, 2, 3, 4]
l2 = []
b = [1,2,3]
for i in range(1,5):
b[1] = i
l2.append(b) # 添加的是b指向的对象,它包括列表元素的引用,列表本身没有改变,只是列表项[1]指向的对象变了
print(l2) # [[1, 4, 3], [1, 4, 3], [1, 4, 3], [1, 4, 3]]
# 不是预料的 [[1, 1, 3], [1, 2, 3], [1, 3, 3], [1, 4, 3]]
可以参考例子5。所以,每次列表实际上都是添加同一个对象。
l2 = []
b = [1,2,3]
for i in range(1,5):
b[1] = i
l2.append(copy.copy(b))
# l2.append(copy.deepcopy(b)) 和copy.copy()结果一样
print(l2) # [[1, 1, 3], [1, 2, 3], [1, 3, 3], [1, 4, 3]]
copy.copy() 浅拷贝。只拷贝父对象,不会拷贝对象的内部的子对象。
那么,copy.copy()和copy.deepcopy()有什么区别呢?
l2 = []
b = [1,[4,5],3]
for i in range(1,5):
b[1][0] = i
l2.append(copy.copy(b)) # [[1, [4, 5], 3], [1, [4, 5], 3], [1, [4, 5], 3], [1, [4, 5], 3]]
# l2.append(copy.deepcopy(b)) # [[1, [1, 5], 3], [1, [2, 5], 3], [1, [3, 5], 3], [1, [4, 5], 3]]
print(l2)
copy.deepcopy() 深拷贝 拷贝对象及其子对象
例子 8:
函数的参数传递探究
def testPara(aList):
aList[0] = 8
print("inside function",aList) # [8, 2, 3]
if __name__ == '__main__':
l1 = [1,2,3]
testPara(l1)
print(l1) # [8, 2, 3]
def testPara(aList):
aList = [1,2]
print("inside function",aList) # [1,2] aList重新指向一个新的对象
if __name__ == '__main__':
l1 = [1,2,3]
testPara(l1)
print(l1) # [1, 2, 3]
这里要想直接把l1在函数内改变,可以在函数return l1
def test(l:list):
l.pop(0)
if __name__ == '__main__':
l = [1,2,3]
test(l)
print(l) # [2,3]
python引用和对象详解的更多相关文章
- Java中对象、对象引用、堆、栈、值传递以及引用传递的详解
Java中对象.对象引用.堆.栈.值传递以及引用传递的详解 1.对象和对象引用的差别: (1).对象: 万物皆对象.对象是类的实例. 在Java中new是用来在堆上创建对象用的. 一个对象能够被多个引 ...
- Python对Excel操作详解
Python对Excel操作详解 文档摘要: 本文档主要介绍如何通过python对office excel进行读写操作,使用了xlrd.xlwt和xlutils模块.另外还演示了如何通过Tcl ...
- Python初学者常见错误详解
Python初学者常见错误详解 0.忘记写冒号 在 if.elif.else.for.while.class.def 语句后面忘记添加 “:” if spam == 42 print('Hello ...
- python基础之函数详解
Python基础之函数详解 目录 Python基础之函数详解 一.函数的定义 二.函数的调用 三.函数返回值 四.函数的参数 4.1 位置参数 4.2 关键字参数 实参:位置实参和关键字参数的混合使用 ...
- python之sys模块详解
python之sys模块详解 sys模块功能多,我们这里介绍一些比较实用的功能,相信你会喜欢的,和我一起走进python的模块吧! sys模块的常见函数列表 sys.argv: 实现从程序外部向程序传 ...
- Window 对象详解 转自 http://blog.csdn.net/jcx5083761/article/details/41243697
详解HTML中的window对象和document对象 标签: HTMLwindowdocument 2014-11-18 11:03 5884人阅读 评论(0) 收藏 举报 分类: HTML& ...
- python中threading模块详解(一)
python中threading模块详解(一) 来源 http://blog.chinaunix.net/uid-27571599-id-3484048.html threading提供了一个比thr ...
- mvc-servlet---ServletConfig与ServletContext对象详解(转载)
ServletConfig与ServletContext对象详解 一.ServletConfig对象 在Servlet的配置文件中,可以使用一个或多个<init-param>标签为s ...
- django中request对象详解(转载)
django中的request对象详解 Request 我们知道当URLconf文件匹配到用户输入的路径后,会调用对应的view函数,并将 HttpRequest对象 作为第一个参数传入该函数. ...
随机推荐
- vue父子组件之间的通信
利用props在子组件接受父组件传过来的值1.父组件parentComp.vue <template> <childComp :fromParentToChild="fro ...
- dubbox系列【四】——使用dubbo-monitor-x监控注册中心
1.下载源码,编译成war包 源码下载地址为:https://git.oschina.net/yjmyzz/dubbo-monitor.git 在pom.xml文件所在目录,直接执行mvn packa ...
- 剑指offer第三天
21.栈的压入.弹出序列 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3, ...
- 《设计模式之禅》--设计模式大PK
创建类模式包括工厂方法模式.建造者模式.抽象工厂模式.单例模式和原型模式. 其中单例模式要保持在内存中只有一个对象,原型模式是要求通过复制的方式产生一个新的对象. [工厂方法(抽象工厂) VS 建造者 ...
- windows NLB实现MSSQL读写分离--从数据库集群读负载均衡
主从模式,几乎大部分出名的数据库都支持的一种集群模式. 当Web站点的访问量上去之后,很多站点,选择读写分离,减轻主数据库的的压力.当然,一主多从也可以作用多个功能,比如备份.这里主要演示如何实现从数 ...
- vim使用教程
vim的学习曲线相当的大(参看各种文本编辑器的学习曲线),所以,如果你一开始看到的是一大堆VIM的命令分类,你一定会对这个编辑器失去兴趣的.下面的文章翻译自<Learn Vim Progress ...
- Zookeeper笔记二-各种一致性协议解释
我们知道Zookeeper的一致性是解决分布式事务的. 那么分布式事务代表的是强一致性. 强一致性解决的代表有以下协议(注意这几个协议跟zookeeper是没任何关系的,这是分布式的理论基础): 1. ...
- Java中的Lock与synchronized
并发编程学习笔记之Lock与synchronized 一.什么是可重入锁 Lcok在Java中是一个接口,一般在面试问题中问到的可能是ReentrantLock与synchronized的区别.Ree ...
- DAVINCI DM6446 开发攻略——V4L2视频驱动和应用分析
针对DAVINCI DM6446平台,网络上也有很多网友写了V4L2的驱动,但只是解析Montavista linux-2.6.10 V4L2的原理.结构和函数,深度不够.本文决定把Montavis ...
- 【memcache】windos下 memcache更改默认的端口和最大使用内存
1>用内网ip的方式提供web应用服务器调用,不允许直接通过外网调用,如将memcache服务器放在192.168.1.55的服务器上 2>修改端口,如改为11200 3>分配内存, ...