Python语言自带垃圾回收机制,为了能够比较清楚说明白Python的垃圾回收机制的原理,我们今天就从最底层的解释器开始,采用由内到外的方式来说明。

1.Python默认解释器CPython

Python语言拥有多种解释器,但是默认采用CPython实现。CPython实际上是用C语言编写的。主要功能如下:

编译python代码为字节码(bytecode)

在虚拟机上面运行编译好的python程序

CPython是用C语言编写的,而C语言本身并不支持面向对象编程。正因为如此,在CPython代码中有很多很有意思的设计,来实现这些原本不支持的的功能。:如PyObject。

PyObject是Python中所有对象的鼻祖,它只包含两种东西:

ob_refcnt: 引用计数

ob_type: 指向另一种类型的指针

ob_refcnt引用计数用于接下来要说明的垃圾收集。

2.垃圾回收机制

2.1 垃圾回收简单说明

Python中的垃圾回收回收机制采用引用计数的策略来实现,当一个对象的ob_refcnt大于0,说明存在引用,此时改对象不会进行垃圾回收。当一个对象 的ob_refcnt的引用数目等于0的时候,说明该对象没有任何引用,说明是一个闲置废弃的对象,会进入垃圾回收的阶段。

Python允许您使用sys模块检查对象的当前引用计数。可以使用sys.getrefcount(numbers),但是要记住,将对象传递给getrefcount()会使引用计数增加1。

下面我们几段代码来演示一下:

2.2 引用计数入门示例

import sys

a1 = [1, 2, 3]

print(sys.getrefcount(a1))

运行结果:

2

程序运行说明:

首先第一次赋值操作,很容易理解变量a1指向的对象[1,2,3]的引用次数为1,然后在调用sys.getrefcount(a1)的时候,会把形参认为是一个局部变量a1,不是全局变量a1,但是对应的值是一样的,所以这个时候会增加一个引用次数,变成2。

2.3 赋值增加引用计数

import sys

a1 = [1, 2, 3]

print(id(a1))

print(sys.getrefcount(a1))

a2 = a1

print(sys.getrefcount(a1))

print(sys.getrefcount(a1))

print("--" * 20)

a3 = [1, 2, 3]

print(id(a3))

print(sys.getrefcount(a3))

运行结果:

4726471808

2

3

3

----------------------------------------

4726471888

2

程序说明: 第一部分和上面的例子是一样的,但是增加一个id(a1)的方法,会打印出a1的内存地址。当执行a2 = a1的时候,增加了一个引用。sys.getrefcount(a1)是同一个,所以两次执行也不会增加引用。虽然a1和a3对应的值是相同的,但是id值不一样,相当是一个新的,所以计算计算引用从1开始计算,增加sys.getrefcount(a1)里面的一个,最后结果为2。

2.4 对象包含在其他数据结构中会增加引用次数

import sys

a1 = [1, 2, 3]

print(sys.getrefcount(a1))

a2 = [a1]

print(sys.getrefcount(a1))

a3 = (a1, )

print(sys.getrefcount(a1))

a4 = {"key1": a1}

print(sys.getrefcount(a1))

运行结果:

2

3

4

5

程序运行说明: 这部分是可以正常理解的。

但是当数据变化的时候,下面的例子,我找了资料也没有具体说清楚:

import sys

a1 = 1

print(sys.getrefcount(a1))

a2 = [a1]

print(sys.getrefcount(a1))

a3 = (a1, )

print(sys.getrefcount(a1))

a4 = {"key1": a1}

print(sys.getrefcount(a1))

运行结果:

4378

4379

4380

4381

程序说明: 这部分的原因是由于Python中对象缓存造成的,对于一些数值较小的对象,会经常使用到,对这一部分对象存在内部的缓存机制。也就是会存在多个引用,具体多少数值,和运行平台、解释器、数值取值大小都有都有印象。 下面通过两段简单代码来说明: 第一段: Python命令行执行

>>> a1=1

>>> id(a1)

140732194454592

>>> a2=1

>>> id(a2)

140732194454592

>>>

>>> b1=257

>>> id(b1)

1878299222992

>>> b2=257

>>> id(b2)

1878301364976

第二段: Pycharm中保存文件执行

a1 = 1

a2 = 1

print(id(a1))

print(id(a2))

b1 = 257

b2 = 257

print(id(b1))

print(id(b2))

b1 = 99999999999999999999999999999999999999999999999

b2 = 99999999999999999999999999999999999999999999999

print(id(b1))

print(id(b2))

运行结果:

140732194454592

140732194454592

2195360849840

2195360849840

2195386463936

2195386463936

通过两组程序我们发现,虽然Python存在对象的缓存机制,但是对于不同的运行环境中,存在一定的差异。在命令行中,以整数为例:[-5, 256]这个区间的范围会被缓存,但是在文件中,无论多大数值都会被缓存。

3.析构方法

3.1 析构方法说明

__del__方法称为"析构方法",用于实现对象被销毁时所需要的操作。比如:释放对象占用的资源。使用场景:

打开的文件资源

网络连接

数据库操作

。。。

Python实现自动的垃圾回收,当对象没有被引用时(引用计数为0),由垃圾回收器调用__del__方法。

我们也可以使用del语句手动删除对象,从而保证调用__del__方法。

系统会自动提供__del__方法,一般不需要自定义析构方法。

3.2 代码示例

代码:

class Person:

def __init__(self, name):

self.name = name

def __del__(self):

print("销毁对象:{0}".format(self.name))

p1 = Person("p1")

p2 = Person("p2")

# 使用del方法主动销毁对象p2

del p2

print("程序结束")

运行结果:

销毁对象:p2

程序结束

销毁对象:p1

代码说明:

因为手动调用del方法注销p2对象,本质上还是调用对象p2本身的注销机制,在注销之前会调用自身的__del__()方法,所以第一行输出销毁对象:p2.

程序代码运行结束,执行打印语句,所以第二行显示:程序结束

python的垃圾回收器,对程序进行处理,发现对象p1目前仍占用内存,没有被清除。启动垃圾回收机制,类似步骤一,所以第三行输出: 销毁对象:p1

备注:

更多精彩博客,请访问:聂发俊的技术博客

对应视频教程,请访问:python400

完整markdown笔记,请访问: python400_learn_github

python垃圾回收 采用方式_python-面向对象-10-__del__析构方法/垃圾回收机制相关推荐

  1. 【软件项目管理】用例分析方法采用一种面向对象的情景分析方法

    用例分析方法采用一种面向对象的情景分析方法. 传统的结构化分析方法是面向功能的,而面向对象的视点是将系统看作一组服务,将问题看作相互作用的实体.用例分析方法采用面向对象的方法,将现实世界的" ...

  2. python面相对象编程指南_Python面向对象编程指南

    抽象是隐藏多余细节的艺术.在面向对象的概念中,抽象的直接表现形式通常为类.虽然Python是解释性语言,但是它是面向对象的,从设计之初就已经是一门面向对象的语言.Python基本上提供了面向对象编程语 ...

  3. python对象和类区别_python面向对象(类与对象)

    面向对象思想 关注公众号"轻松学编程"了解更多. 1.面向对象的设计思想 面向对象是基于万物皆对象这个哲学观点. 2.面向对象和面向过程的区别 面向过程 在生活中: 它是一种看待问 ...

  4. 下列哪个不是python元组的定义方式_Python基础知识笔试

    Python基础知识笔试 单选题(2.5分*20题) 1. 下列哪个表达式在Python中是非法的? B A. x = y = z = 1 B. x = (y = z + 1) C. x, y = y ...

  5. python爬虫有多少种方式_python爬虫-----Python访问http的几种方式

    爬取页面数据,我们需要访问页面,发送http请求,以下内容就是Python发送请求的几种简单方式: 会使用到的库  urllib   requests 1.urlopen import urllib. ...

  6. python源文件的执行方式_python源程序执行的方式有哪几种

    执行python程序有如下三种方式: 一.解释器 例如在命令行输入:python D:/Code/Python/Hello.py python的解释器:Cpython,pypy等. 二.交互式 所谓交 ...

  7. python编程多行输入_python多行输入的方法有哪些

    python多行输入的方法有哪些 发布时间:2020-09-02 14:48:45 来源:亿速云 阅读:72 作者:小新 小编给大家分享一下python多行输入的方法有哪些,相信大部分人都还不怎么了解 ...

  8. python拷贝是什么知识点_python闭包、深浅拷贝、垃圾回收、with语句知识点汇总...

    1.1 闭包 1.闭包概念 1. 在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用,这样就构成了一个闭包 2. 一般情况下,在我们认知当中,如果一个函数 ...

  9. python对象三个特性_python面向对象的三大特性

    一.继承 面向对象中的继承就是继承的类直接拥有被继承类的属性而不需要在自己的类体中重新再写一遍,其中被继承的类叫做父类.基类,继承的类叫做派生类.子类.在python3中如果不指定继承哪个类,默认就会 ...

最新文章

  1. 全面梳理关系型数据库和 NoSQL 的使用情景
  2. Java线程详解(15)-阻塞队列和阻塞栈
  3. ACM常见问题之【求逆序对】
  4. Java对象容器——顺序容器及常用方法
  5. 中国企业海外人才发展白皮书
  6. php中的oop,在现有PHP中加入OOP
  7. Partition List,拆分链表
  8. 延长计算机屏幕显示时间,如何设置电脑显示屏保时间
  9. js基础-点击切换div背景颜色
  10. cad打开卡死_CAD点打开或者保存就卡死无响应的解决方法
  11. Oracle11g的安装及删除
  12. 阿里巴巴、腾讯投资Barefoot,助力C轮融资8000万美元
  13. 75道程序员面试逻辑思维题及答案解析
  14. 如何用U盘进行装机?
  15. 北京工作居住证的申请条件和可享受的待遇
  16. 你的typora图床配置了吗?人家都开始收费了
  17. 中国科技技术大学潘建伟计算机,中国研制量子计算机“九章” 比超级计算机快一百万亿倍...
  18. background-attachment: fixed/scroll
  19. 2021年高新技术企业认定时间及条件出来了,全国28省
  20. 4、oracle使用网络管理工具—Net Manager添加本地监听程序

热门文章

  1. python画图配色_python matplotlib包图像配色方案分享
  2. 【linux】设置镜像源
  3. ipynb文件转为python(.py)文件
  4. 用法 stl_C++STL 容器篇
  5. 直接插入排序比较次数_程序员必须要会的直接插入排序算法
  6. Cocos creator -引擎解构
  7. 手机h5可以用ifreme_折叠照片特效,用手机修图软件就可以实现
  8. JS模块化编程require.js简介
  9. 现代软件工程 作业 团队第一个作业
  10. php 命名空间通俗易懂_PHP进阶由浅入深掌握面向对象开发