前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python 对象引用、可变性 和 垃圾回收

python 对象引用、可变性 和 垃圾回收

作者头像
Michael阿明
发布2021-09-06 11:21:48
3670
发布2021-09-06 11:21:48
举报
文章被收录于专栏:Michael阿明学习之路

文章目录

learn from 《流畅的python》

1. 变量是标签

代码语言:javascript
复制
>>> a = [1, 2, 3] 
>>> b = a 
>>> a.append(4) 
>>> b 
[1, 2, 3, 4]
在这里插入图片描述
在这里插入图片描述
  • 对象的 id 在生命周期中是不变的
  • is 运算检查两者的 id 是否一致
  • == 检查两者内容(值)是否一样
  • is 运算符比 == 速度快,因为它不能重载,不用寻找并调用特殊方法

2. 元组的相对不可变性

元组的不可变性 其实是指 tuple 数据结构的 物理内容(即保存的引用)不可变,与引用的对象无关

代码语言:javascript
复制
>>> t1 = (1, 2, [30, 40])
>>> t2 = (1, 2, [30, 40])
>>> t1 is t2
False
>>> t1 == t2
True
>>> id(t1[-1])
2633996005896
>>> t1[-1].append(100)
>>> t1
(1, 2, [30, 40, 100])
>>> id(t1[-1])
2633996005896
>>> t1 == t2
False

如果元组内部有 可变对象,那么元组就 不可散列了

3. 默认浅复制

代码语言:javascript
复制
>>> l1 = [3, [55, 44], (7, 8, 9)]
>>> l2 = list(l1) # 创建副本 或者 [:] ,浅复制
>>> l2
[3, [55, 44], (7, 8, 9)]
>>> l1 == l2
True
>>> l1 is l2
False

构造方法[:] 做的是浅复制(即复制了最外层容器,副本中 的元素是源容器中元素的引用)。 如果所有元素都是不可变的,那么这 样没有问题,还能节省内存。 但是,如果有可变的元素,可能就会导致 意想不到的问题。

代码语言:javascript
复制
>>> l1 = [3, [66, 55, 44], (7, 8, 9)]
>>> l2 = list(l1)  # 两者共享内部的 list tuple
>>> l1.append(100)
>>> l1[1].remove(55)
>>> print('l1:', l1)
l1: [3, [66, 44], (7, 8, 9), 100]
>>> print('l2:', l2)
l2: [3, [66, 44], (7, 8, 9)]
>>> l2[1] += [33, 22]   # list 变更,反映到 l1
>>> l2[2] += (10, 11)  # tuple 不可变,+= 生成新的 tuple ,不反映到 l1
>>> print('l1:', l1)
l1: [3, [66, 44, 33, 22], (7, 8, 9), 100]
>>> print('l2:', l2)
l2: [3, [66, 44, 33, 22], (7, 8, 9, 10, 11)]
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  • copy 模块 的 deepcopy(),copy() 实现 深复制,浅复制

4. 函数的参数作为引用时

  • 可变对象 经过函数修改会传递出来(如果不希望修改原来的,可以创建副本)
  • 不可变对象 操作后,会生成新的对象
  • 不要用 可变对象作为函数默认值,如 def func(a = [])
代码语言:javascript
复制
>>> def func(a=[]):
...     a.append(5)
...     print(a)
...
>>> func()
[5]
>>> func()
[5, 5]
>>> func()
[5, 5, 5]

修改了 可变的默认值,后续调用都会受到影响

5. del 和 垃圾回收

del 语句删除名称,而不是对象 del 命令可能会导致对象被 当作垃圾 回收,但是 仅当 删除的变量 保存的是 对象的最后一个引用,或者无法得 到对象时

6. 弱引用

正是因为有引用,对象才会在内存中存在。

当对象的引用数量归零后, 垃圾回收程序会把对象销毁。

但是,有时需要引用对象,而不让对象 存在的时间超过所需时间。这经常用在缓存中。

弱引用不会增加对象的引用数量。 引用的目标对象 称为 所指对象 (referent)。弱引用 不会妨碍 所指对象被当作垃圾回收。 弱引用在缓存应用中很有用,因为我们 不想仅因为 被缓存引用着 而始终 保存缓存对象

7. 一些可能的坑!!!

代码语言:javascript
复制
>>> a = None
>>> b = None
>>> a is b
True
>>> id(a)
140712131987472
>>> id(b)
140712131987472
>>> a = [1,2]
>>> b = [1,2]
>>> a is b
False
>>> a = (1,2)  # list , tuple 相同字面量,id 不同
>>> b = (1,2)
>>> a is b
False
>>> a = "haha"  # 相同的字面量字符串,id 一样!!
>>> b = "haha"
>>> a is b
True
>>> a = 5
>>> b = 5
>>> a is b
True
代码语言:javascript
复制
>>> a, b = 0 , 0
>>> a is b
True
>>> a = 5
>>> a
5
>>> b
0
>>> a = "ha"
>>> b = "ha"
>>> a is b
True
>>> a = "good"  # 但是也无须担心。。
>>> a
'good'
>>> b
'ha'
代码语言:javascript
复制
>>> a = [1,2]
>>> b = a[:]
>>> b
[1, 2]
>>> a is b
False
>>> a = (1,2)
>>> b = a[:]  # 不创建新的副本,而list会创建新的副本
>>> b
(1, 2)
>>> a is b
True
>>> b = tuple(a) # 不创建新的副本,而list会创建新的副本
>>> a is b
True
代码语言:javascript
复制
>>> a = [1,2]
>>> b = list(a) # list 创建副本
>>> b
[1, 2]
>>> a is b
False
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/07/22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 1. 变量是标签
  • 2. 元组的相对不可变性
  • 3. 默认浅复制
  • 4. 函数的参数作为引用时
  • 5. del 和 垃圾回收
  • 6. 弱引用
  • 7. 一些可能的坑!!!
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档