举例子来说明Python引用和对象
2018-06-18 02:06:17来源:未知 阅读 ()
今天看到这么一句奇怪的话: python中变量名和对象是分离的;最开始的时候是看到这句话的时候没有反应过来。决定具体搞清楚一下python中变量与对象之间的细节。(其实我感觉应该说 引用和对象分离 更为贴切)
从最开始的变量开始思考:
在python中,如果要使用一个变量,不需要提前进行声明,只需要在用的时候,给这个变量赋值即可 (这个和C语言等静态类型语言不同,和python为动态类型有关)。
举第一个例子:
a = 1
这是一个简单的赋值语句,整数 1 为一个对象,a 是一个引用,利用赋值语句,引用a指向了对象1;这边形象比喻一下:这个过程就相当于“放风筝”,变量a就是你手里面的“线”,python就跟那根“线”一样,通过引用来接触和拴住天空中的风筝——对象。
你可以通过python的内置函数 id() 来查看对象的身份(identity),这个所谓的身份其实就是 对象 的内存地址:
注:
python一切皆对象的理念,所以函数也是一个对象,因此可以使用 id() 函数的__doc__方法来查看这个函数的具体描述。
先举个例子:
>>> a = 1
>>> id(a)
24834392
>>> a = 'banana'
>>> id(a)
139990659655312
第一个语句中, 2是储存在内存中的一个整数对象,通过赋值 引用a 指向了 对象 1;
第二个语句中,内存中建立了一个字符串对象‘banana’,通过赋值 将 引用a 指向了 ‘banana’,同时,对象1不在有引用指向它,它会被python的内存处理机制给当我垃圾回收,释放内存。
再举一个例子:
>>> a = 1
>>> id(a)
24834392
>>> a = 'banana'
>>> id(a)
139990659655312
第一个语句中, 2是储存在内存中的一个整数对象,通过赋值 引用a 指向了 对象 1;
第二个语句中,内存中建立了一个字符串对象‘banana’,通过赋值 将 引用a 指向了 ‘banana’,同时,对象1不在有引用指向它,它会被python的内存处理机制给当我垃圾回收,释放内存。
再来一个例子:
通过函数查看 变量a 和 变量b的引用情况:
1
2
3
4
5
6
|
>>> a = 3 >>> b = 3 >>> id (a) 10289448 >>> id (b) 10289448 |
在这里可以看到 这俩个引用 指向了同一个 对象,这是为什么呢? 这个跟python的内存机制有关系,因为对于语言来说,频繁的进行对象的销毁和建立,特别浪费性能。所以在Python中,整数和短小的字符,Python都会缓存这些对象,以便重复使用。
然后再看看这个例子:
1. a = 4
2. b = a(这里就是让引用b指向引用a指向的那个对象)
3. a = a + 2
通过函数查看引用情况:
当执行到第2步的时候,查看一下 a 和 b 的引用:
1
2
3
4
5
6
|
>>> a = 4 >>> b = a >>> id (a) 36151568 >>> id (b) 36151568 |
可以看到 a 和 b 都指向了 整数对象 4
接下来指向第3步:
1
2
3
4
5
|
>>> a = a + 2 >>> id (a) 36151520 >>> id (b) 36151568 |
可以看到 a 的引用改变了,但是 b 的引用未发生改变;a,b指向不同的对象; 第3句对 a 进行了重新赋值,让它指向了新的 对象6;即使是多个引用指向同一个对象,如果一个引用值发生变化,那么实际上是让这个引用指向一个新的引用,并不影响其他的引用的指向。从效果上看,就是各个引用各自独立,互不影响。
还有一个必须要看的例子:
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]]
所以,每次列表实际上都是添加同一个对象。
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() 深拷贝 拷贝对象及其子对象。
最后一个例子:
(这个栗子会涉及到 python中的 可变数据类型 和 不可变数据类型):
开始这个栗子之前,请记得注意到 第四个栗子的不同之处。
1. L1 = [1, 2, 3]
2. L2 = L1
3. L1[0] = 10
通过函数查看引用情况:
当执行第1步 和 第二步 的时候,查看一下 L1 和 L2 的引用情况:
1
2
3
4
5
6
|
>>> L1 = [ 1 , 2 , 3 ] >>> L2 = L1 >>> id (L1) 139643051219496 >>> id (L2) 139643051219496 |
此时 L1 和 L2 的引用相同,都是指向 [1,2,3]这个列表对象。
接下来,继续执行第3步:
1
2
3
4
5
6
7
|
>>> 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.
感谢阅读上海尚学堂python文章,获取更多文章和技术支持,请点击 上海Python培训
推荐一下相关文章:《Python基础学习之字符编码、交互输入和字符串拼接》;《谈谈Python中的*args 和 **kwargs》;《Python的函数参数传递》等
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- Python连载30-多线程之进程&线程&线程使用 2019-08-13
- python学习-26 函数作用域 2019-07-24
- 闯越自动签到demo版补充说明 2019-07-24
- Django项目之Web端电商网站的实战开发(三) 2019-04-11
- Python破解Wifi密码思路 2019-03-01
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash