以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、CAD2008怎么删除?AutoCAD2008删除方法分享3229
  2. 2、果备份如何备份手机照片?果备份备份照片的详细方法3498
  3. 3、Win7系统资源管理器搜索不到文件怎么办?4060
  4. 4、Win1020H2怎么升级21H1怎么升级win10系统版本到21H12236
  5. 5、kk录像机如何使用kk录像机使用方法3490
  6. 6、可可英语怎么收藏文章?可可英语收藏文章的方法2190
  7. 7、Win10怎么提升dota2帧数?提升dota2帧数的操作步骤2687
  8. 8、天气通如何设置语音播报?天气通设置语音播报的方法3383
  9. 9、如何减少Windows7旗舰版系统电脑内存占用率加快系统运行速度?4732
  10. 10、个人所得税app怎么切换账号?个人所得税app切换账号的方法1309
全部评论(0)
我也有话说
0
收藏
点赞
顶部