以Python语言为例探讨语音内存管理方式

语言的内存管理是语言设计的一个重要方面。它是决定语言性能的重要因素。无论是C语言的手工管理,还是     Java   的垃圾回收,都成为语言最重要的特征。这里以     Python   语言为例子,说明一门动态类型的、面向对象的语言的内存管理方式。

对象的内存使用

赋值语句是语言最常见的功能了。但即使是最简单的赋值语句,也可以很有内涵。Python的赋值语句就很值得研究。

a = 1

整数1为一个对象。而a是一个引用。利用赋值语句,引用a指向对象1。Python是动态类型的语言(参考 动态类型 ),对象与引用分离。Python像使用“筷子”那样,通过引用来接触和翻动真正的食物——对象。

 以Python语言为例探讨语音内存管理方式_设计制作_可编程逻辑

引用和对象

为了探索对象在内存的存储,我们可以求助于Python的内置函数 id() 。它用于返回对象的身份(iden     ti   ty)。其实,这里所谓的身份,就是该对象的 内存地址 。

a = 1

print(id(a))
print(hex(id(a)))
在我的计算机上,它们返回的是:

11246696
'0xab9c68'


分别为内存地址的十进制和十六进制表示。

在Python中,整数和短小的字符,Python都会缓存这些对象,以便重复使用。当我们创建多个等于1的引用时,实际上是让所有这些引用指向同一个对象。

a = 1
b = 1
print(id(a))
print(id(b))


上面程序返回

11246696
11246696


可见a和b实际上是指向同一个对象的两个引用。

为了检验两个引用指向同一个对象,我们可以用 is 关键字。is用于判断两个引用所指的对象是否相同。


# Truea = 1 b = 1 print(a is b) # True a = "good" b = "good" print(a is b) # False a = "very good morning" b = "very good morning" print(a is b) # False a = [] b = [] print(a is b)


上面的注释为相应的运行结果。可以看到,由于Python缓存了整数和短字符串,因此每个对象只存有一份。比如,所有整数1的引用都指向同一对象。即使使用赋值语句,也只是创造了新的引用,而不是对象本身。长的字符串和其它对象可以有多个相同的对象,可以使用赋值语句创建出新的对象。


在Python中,每个对象都有存有指向该对象的引用总数,即 引用计数 (reference count)。

我们可以使用 sys 包中的 getrefcount() ,来查看某个对象的引用计数。需要注意的是,当使用某个引用作为参数,传递给getrefcount()时,参数实际上创建了一个临时的引用。因此,getrefcount()所得到的结果,会比期望的多1。


f     rom   sys import getrefcount a = [1, 2, 3] print(getrefcount(a)) b = a print(getrefcount(b))
由于上述原因,两个getrefcount将返回2和3,而不是期望的1和2。


对象引用对象

Python的一个容器对象(cont     ai   ner),比如表、词典等,可以包含多个对象。实际上,容器对象中包含的并不是元素对象本身,是指向各个元素对象的引用。

我们也可以自定义一个对象,并引用其它对象:


class from_obj(object):     def __init__(self, to_obj):         self.to_obj = to_obj b = [1,2,3] a = from_obj(b) print(id(a.to_obj)) print(id(b))


可以看到,a引用了对象b。


对象引用对象,是Python最基本的构成方式。即使是a = 1这一赋值方式,实际上是让词典的一个键值"a"的元素引用整数对象1。该词典对象用于记录所有的全局引用。该词典引用了整数对象1。我们可以通过内置函数 globals() 来查看该词典。

当一个对象A被另一个对象B引用时,A的引用计数将增加1。


from sys import getrefcount a = [1, 2, 3] print(getrefcount(a)) b = [a, a] print(getrefcount(a))


由于对象b引用了两次a,a的引用计数增加了2。


容器对象的引用可能构成很复杂的拓扑结构。我们可以用objgraph包来绘制其引用关系,比如


x = [1, 2, 3] y = [x, dict(key1=x)] z = [y, (x, y)] import objgraph objgraph.show_refs([z], filename='ref_topo.png')

 以Python语言为例探讨语音内存管理方式_设计制作_可编程逻辑

objgraph是Python的一个第三方包。安装之前需要安装xdot。

sudo apt-get install xdot sudo     pi   p install objgraph


objgraph官网

两个对象可能相互引用,从而构成所谓的 引用环 (reference cycle)。

a = []
b = [a]
a.append(b)


即使是一个对象,只需要自己引用自己,也能构成引用环。

a = []
a.append(a)
print(getrefcount(a))


引用环会给垃圾回收机制带来很大的麻烦,我将在后面详细叙述这一点。

68
171
0
11

相关资讯

  1. 1、《奇迹MU》回忆专题上线老玩家齐聚话旧情1219
  2. 2、《风云》雄霸三个弟子中,聂风武学资质不是最强?雄霸说出了答案2127
  3. 3、程丽莎自曝为上节目打针导致脸僵,被老公吐槽:不作不死!4623
  4. 4、英语成绩总是差?这款入耳式设备可以帮助学习新语言1046
  5. 5、冯小刚自曝萌生退意称拍《私人订制》为还人情3878
  6. 6、《你的婚礼》领跑,2021年五一档总票房破9亿4762
  7. 7、王力宏上《吐槽大会》公开学霸家世惹人艳羡,而他的表情包更抢眼4124
  8. 8、iOS12的“屏幕使用时间”会让“第三方工具APP”地震么?4644
  9. 9、《剑绝》惊现百人械斗跨服砍杀战不休827
  10. 10、《他在逆光中告白》情节高能,男主厉腾的真实身份呼之欲出!3156
全部评论(0)
我也有话说
0
收藏
点赞
顶部