【Python语言基础】19、垃圾回收

打印 上一主题 下一主题

主题 1739|帖子 1739|积分 5217

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
1. 垃圾回收

计算机的内存想象成一个大仓库,里面存放着各种各样的货品(对象),而 Python 的垃圾回收机制就如同仓库里的清洁工,会定期检查房间(内存),把那些你不再利用的物品(对象)清理掉,释放出空间,让你可以继续利用内存。
而在程序中没有被引用的对象就是垃圾,垃圾对象过多会影响到程序的运行速率。
下面咱们就联合生活场景具体说说。
1.1 引用计数-一样平常检查货品标签

在这个大仓库中,每一件货品上都挂着标签,每个标签代表着一个对该货品的引用。
好比,有一个叫 “苹果” 的货品,当仓库管理员小王在他的货品清单上记录了 “苹果” 时,“苹果” 这个货品就有了一个标签,代表小王引用了它。
  1. # 仓库里新来了一批苹果
  2. apples = ["红富士", "蛇果"]  
  3. # 小李也在他的清单上记录了苹果
  4. other_apples = apples  
复制代码
此时,“苹果” 货品上就有了两个标签,意味着它的引用计数是 2。
当小王不再需要 “苹果” 了,他会从自己的清单上划掉 “苹果”,这就相当于删除了一个引用。
  1. # 小王不再关注苹果了
  2. del apples  
复制代码
这时,“苹果” 货品上就只剩下一个标签,引用计数变为 1。
如果小李也不再需要 “苹果”,从他的清单上划掉 “苹果”,引用计数就变为 0。
  1. # 小李也不再关注苹果了
  2. del other_apples  
复制代码
一旦引用计数为 0,清洁工(垃圾回收机制)就会立刻发现,然后把 “苹果” 货品从仓库中清理出去,释放出存放 “苹果” 的空间。
1.2 标记-清除算法:处理互相依靠的货品

有时候,仓库里会出现一些特别环境,有两件货品相互捆绑在一起,而且没有其他地方提到它们。
好比,“箱子” 货品里面装着 “钥匙” 货品,同时 “钥匙” 又能打开 “箱子”,它们相互依靠。
  1. class Box:
  2.     pass
  3. class Key:
  4.     pass
  5. # 仓库里有了一个箱子和一把钥匙
  6. box = Box()
  7. key = Key()
  8. # 箱子里装着钥匙
  9. box.key = key
  10. # 钥匙能打开箱子
  11. key.box = box
  12. # 仓库管理员不再需要它们了
  13. del box
  14. del key
复制代码
在这种环境下,“箱子” 和 “钥匙” 固然看起来没人要了,但因为它们相互引用,各自的引用计数都不为 0。
这时,一样平常检查标签的方法(引用计数)就失效了。
于是,清洁工就会启动标记 - 清除算法。他先把仓库里所有的货品都标记为 “可能要清理”,然后从仓库的入口(根对象,如全局变量)开始,沿着货品之间的关联关系进行检查。
如果发现某个货品可以从入口到达,就把它标记为 “保留”。经过一轮检查后,那些仍然标记为 “可能要清理” 的货品,就是真正的垃圾,清洁工就会把它们清理掉。
1.3 分代回收:根据货品新旧安排清理频率

仓库里的货品有新有旧,有些货品刚进来没多久就可能会被处理掉,而有些货品则会长期存放在仓库里。
清洁工根据这个特点,把货品分成了三代。
新进入仓库的货品属于第 0 代,清洁工对第 0 代货品的检查频率最高,因为它们很可能很快就会变成垃圾。
经过一次检查后还没被清理掉的货品,就会被移到第 1 代。第 1 代货品的检查频率会相对低一些。
而那些经过多次检查都还没被清理的货品,会被移到第 2 代,第 2 代货品的检查频率最低。
  1. # 这是新进来的第 0 代货物
  2. new_item = [1, 2, 3]
  3. # 经过一段时间,new_item 如果没被清理,可能会进入第 1 代
  4. # 再经过一段时间,如果还没被清理,可能会进入第 2 代
复制代码
通过这种分代回收的方式,清洁工可以更高效地管理仓库空间,优先处理那些更可能成为垃圾的货品。
总结
Python 的垃圾回收机制就像这位智慧的清洁工,通过引用计数、标记 - 清除算法和分代回收算法,井井有条地管理着计算机的内存仓库。
2. 特别方法

在 Python 里,特别方法(也叫把戏方法)是一类具有特别名称的方法,它们的名字以双下划线 __ 开头和结尾。这些方法能让你自界说类的行为,使类的利用更符合 Python 的习惯。
特别方法一般不需要我们手动调用,需要在一些特别环境下主动实行
2.1 构造和析构方法



  • __init__:这是最常用的特别方法之一,用于在创建对象时进行初始化操作。
  1. class Person:
  2.     def __init__(self, name, age):
  3.         self.name = name
  4.         self.age = age
  5. p = Person("张三", 25)
复制代码


  • __del__:当对象被销毁时会调用这个方法,可用于实行一些清理操作,好比关闭文件、释放资源等。
  1. class Resource:
  2.     def __init__(self):
  3.         print("资源已创建")
  4.     def __del__(self):
  5.         print("资源已释放")
  6. r = Resource()
  7. del r
复制代码
2.2 字符串表现方法



  • __str__:用于返回对象的字符串表现情势,通常供用户阅读。当利用 print 函数打印对象或利用 str() 函数转换对象时会调用该方法。
  1. class Book:
  2.     def __init__(self, title):
  3.         self.title = title
  4.     def __str__(self):
  5.         return f"这本书的名字是 {self.title}"
  6. book = Book("Python入门")
  7. print(book)
复制代码


  • __repr__:返回对象的 “官方” 字符串表现情势,通常用于调试和开发。当在交互式环境中直接输入对象名或利用 repr() 函数时会调用该方法。
  1. class Point:
  2.     def __init__(self, x, y):
  3.         self.x = x
  4.         self.y = y
  5.     def __repr__(self):
  6.         return f"Point({self.x}, {self.y})"
  7. point = Point(1, 2)
  8. print(repr(point))
复制代码
2.3 比力方法



  • __eq__:用于界说对象的相称比力规则,当利用 == 运算符比力两个对象时会调用该方法。
  1. class Student:
  2.     def __init__(self, id):
  3.         self.id = id
  4.     def __eq__(self, other):
  5.         return self.id == other.id
  6. s1 = Student(1)
  7. s2 = Student(1)
  8. print(s1 == s2)
复制代码
雷同的还有 ne(不等于)、lt(小于)、le(小于等于)、gt(大于)、ge(大于等于)等方法。
2.4 容器相干方法



  • __len__:用于返回对象的长度,当利用 len() 函数时会调用该方法。
  1. class MyList:
  2.     def __init__(self, items):
  3.         self.items = items
  4.     def __len__(self):
  5.         return len(self.items)
  6. my_list = MyList([1, 2, 3])
  7. print(len(my_list))
复制代码


  • __getitem__:用于实现通过索引访问对象中的元素,当利用 obj[index] 这种方式访问对象时会调用该方法。
  1. class MyList:
  2.     def __init__(self, items):
  3.         self.items = items
  4.     def __getitem__(self, index):
  5.         return self.items[index]
  6. my_list = MyList([1, 2, 3])
  7. print(my_list[1])
复制代码
还有 setitem(用于设置元素)、delitem(用于删除元素)等方法。
2.5 可调用对象方法



  • __call__:让对象可以像函数一样被调用。
  1. class Adder:
  2.     def __call__(self, a, b):
  3.         return a + b
  4. adder = Adder()
  5. result = adder(3, 5)
  6. print(result)
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

兜兜零元

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表