垃圾回收机制
【一】什么是垃圾回收机制
-
垃圾回收机制(GC机制)是python自带的机制
-
专门用来回收变量值所占的内存空间
【二】在python中的垃圾
# 每次书写Python代码都会创建很多变量名和变量值
# 但是有很多变量名和变量值 用过一次就不用了
# ---> 被称之为垃圾 ---> 不会主动清理掉垃圾
# name = 'dream'
# print(name)
# del name
# print(name)
# 在python解释器内部自带了一个垃圾回收机制
【三】堆和栈的概念
堆区:变量名和值内存地址关联的区域
栈区:变量值存放的区域
【四】三个名词
引用计数为主,标记清除为辅助,分代回收
【1】引用技术
变量值被变量名指向的次数
看10被指向的次数
# x = 10 # 1次
# y = x # 2次
# x = 11 #1次
# y = 12 #0次
【2】标记清除
当一个变量值被引用的时候,python自带的垃圾回收机制会定期扫描
若这个变量值有引用,则不管
若这个变量值没有引用,则标记
【3】分代回收
-
新生代 ---> 第一次扫描发现没人占用 扔到新生代
-
青春代 ---> 达到新生代扫描阈值后,若还没人指向他,则挪到青春代
-
老年代 ---> 达到青春代扫描阈值后,若还没人指向他,则挪到青春代
-
清除--->达到老年代扫描阈值后,若还没人指向直接清除 del
【4】补充
# 【1】堆区
# 变量值存放于堆区,内存管理回收的则是堆区的内容
# # 在Python中,变量和它们所引用的对象(如数值、字符串、列表、字典等)的存储位置与内存管理机制密切相关。
# # 这里提到的“变量值存放于堆区”主要涉及两个概念:变量本身和它所引用的对象。
# # 1. 变量
# 变量是程序中用于标识数据的一个符号或名字,它并不直接存储数据,而是指向(或引用)实际存储数据的内存地址。
# 在Python解释器内部,变量名通常保存在栈(Stack)中。栈是一种后进先出(LIFO)的数据结构,用于高效地管理函数调用时的局部变量、返回地址等信息。
# 当创建一个变量时,Python会在当前作用域(如全局作用域或函数局部作用域)的栈空间内为该变量分配一个名称,并将其关联到相应的对象。
# # 2. 对象及值
# Python中的对象(即变量所引用的实际数据)通常存储在堆(Heap)中。
# 堆是一种动态分配内存的区域,相比于栈,其大小更为灵活且无固定上限。
# 堆用于存储需要大量、不固定大小内存空间的数据结构,如大数组、复杂的数据类型(如类实例)、以及那些生命周期可能跨越多个函数调用或作用域的对象。
# # 将对象值存放在堆区有以下几个原因:
# # - 灵活性
# 堆内存的大小可以动态调整,能够适应不同大小和复杂度的对象。
# 这使得Python可以在运行时根据需要创建任意大小的对象,无需预先确定其具体尺寸,非常适合处理变长数据结构(如列表、字典)。
# # - 共享性
# 多个变量可以同时引用同一块堆内存中的对象,实现对象的共享。
# 这种机制允许通过赋值、参数传递、返回值等方式高效地复制“引用”,而不是复制整个对象内容,节省了内存资源并提高了效率。
# # - 垃圾回收
# 由于堆内存中的对象可能存在多个引用,Python使用垃圾回收(Garbage Collection, GC)机制自动追踪和管理对象的生命周期。
# 当一个对象不再有任何引用时,GC会识别并释放其占用的堆内存,防止内存泄漏。
# 堆区便于实施这样的垃圾回收策略,确保程序长期运行时内存的有效利用。
# # 综上所述
# Python将变量值(即对象)存放于堆区,主要是为了提供灵活的内存分配、支持对象共享以及实现自动化的垃圾回收,这些特性对于编写高效、健壮的Python程序至关重要。
# 而变量本身作为对象的引用,则通常存储在栈区,便于快速访问和管理其生命周期。
# 【2】栈区
# 变量名与值内存地址的关联关系通常被存放于程序的栈区
# # 1. 栈区的特性与作用
# 栈(Stack)是计算机内存中的一种数据结构,其主要特点是后进先出(LIFO)。在编程语言执行过程中,栈区用于存储局部变量、函数参数以及函数调用时的返回地址等临时性信息。
# 栈区的操作快速且高效,因为它遵循简单的压栈(push)和弹栈(pop)规则,适合处理那些生命周期短、使用频繁且需要保持特定顺序的数据。
# # 2. 变量生命周期管理
# 变量名与值内存地址的关联关系本质上是一种符号表信息,它记录了源代码中定义的变量名与其所对应的内存地址之间的映射。
# 这种信息具有明显的生命周期特征:当进入一个作用域(如函数或代码块)时,新声明的变量及其关联关系应被创建;
# 当离开该作用域时,这些变量及关联关系应被自动清理以释放资源。栈区恰好符合这种对变量生命周期进行严格管理的需求。
# 每当函数调用发生时,会在栈顶为该函数分配一块空间,用于存放其内部声明的变量及其关联关系;函数调用结束时,这部分栈空间会被自动回收
# # 3. 性能优化
# 栈区访问速度极快,因为它的内存地址通常连续且靠近CPU寄存器。将变量名与值内存地址的关联关系放在栈上,可以确保编译器和运行时系统能以较低的时间成本查找并操作这些信息。特别是在递归调用、循环等频繁涉及变量访问的场景下,栈区的高效访问对于提升程序整体性能至关重要
# # 4. 内存安全性
# 栈区的内存由编译器自动分配和释放,不易出现内存泄漏问题。将变量名与值内存地址的关联关系存储在栈上,有助于防止因程序员手动管理内存不当而导致的错误。此外,栈区的大小通常有限制,这有助于防止因局部变量过度使用内存而导致的堆栈溢出问题,从而提高程序稳定性
# # 5. 线程安全性
# 每个线程都有自己的栈空间,这意味着不同线程中的同名局部变量各自拥有 ** 的内存地址和关联关系,互不影响。这一特性保证了并发环境下的数据安全,避免了线程间的数据混淆。
# # 综上所述
# 将变量名与值内存地址的关联关系存放于栈区,既利用了栈区的特性实现了高效的内存管理、快速访问和严格的生命周期控制,又确保了内存安全性与线程安全性,有利于编写稳定、高效且易于维护的程序代码。
# 当然,需要注意的是,上述讨论主要针对局部变量。
# 对于静态变量、全局变量或动态分配的对象,它们的内存地址关联关系可能存在于数据段(Data Segment)或堆区(Heap),而非栈区。
【5】小整数池
# [-5,256] ---> 提前开辟好一块内存空间存储这些数据
# 为了防止频繁的使用数字减少开销
# 不需要每次定义的时候都开辟空间,只需要从开辟好的空间中获取即可
a = 10
b = 10
print(a is b)
True
字符编码
- 为什么学字符编码
- 不同国家有不同文字,怎样让python代码识别不同国家的文字
- 指定好指定的模板让python使用
【一】数据存放位置
我们学的所有数据都存放在内存当中
如何将数据保存到硬盘中
【二】字符编码介绍
-
计算机能识别的文字(二进制数据)与我们能识别的文字之间的对应关系做成的编码表
-
人类与计算机交互的时候,计算机展示出来的内容都是人类可以看得懂的
-
我们都知道计算机只能识别二进制数据
-
二进制就是 0 / 1
-
要学习如何将我们的文字转换成计算机可以识别的文字
【三】字符编码的发展史
# 字符编码是如何从 0 / 1 -----> 文字 / 字符
【1】一家独大
美国人发明计算机 ---> 美国人用英语(英语字符)
0 / 1 编码麻烦 ---> 用字符代表一串代码
---> ASCII 码表 ---> 大小写英文字符 / 数字 / 标点符号
大写英文字母 A-Z : 65 -90
小写英文字母 a-z : 97-122
数字 0 - 9 : 48 - 57
【2】诸侯割据
随着计算机的普及 其他国家的人也能拿到计算机
基于ASCII码表继续扩展,扩展成各个国家的编码表
于是出现了很多编码表
日本 Shift_JIS
中国 GBK
# 问题诞生
# 有一天美国的程序员(ASCII码)拿着他写的代码来找中国人开发
# 韩国人(Euc-kr) --> 中国人开发
# 很多个国家的编码表我都需要保存一遍
【3】一统天下
大家统一意见,合理开发一个编码表,作为所有国家的标志
# Unicode : 存在所有语言中的所有字符与数字的一一对应关系,即兼容万国字符
# 自己国家的字符存储在硬盘中的
# 如果要使用 ---> 读出来 ---> 展示
# 美国人--ascii ---> unicode ----> gbk ---> 中文
# 日本人--shift-jis ---> unicode ----> gbk ---> 中文
【四】如何进行编解码(二进制)
# 1.解码---> 将二进制数据转换为字符
data = b'\xe7\x8e\x8b'
print(data.decode('utf-8'))
# print(data.decode('gbk'))
# print(data.decode('shift-jis'))
王
# 2.编码
name = '王'
# 指定编码格式--->哪种语言的二进制数据
print(name.encode('utf-8'))
b'\xe7\x8e\x8b'
name1 = b'yi'
print(type(name1))
<class 'bytes'>
【五】UTF-8的诞生
# 【1】一开始的保存方案
# 如果保存到硬盘的是GBK格式二进制,当初用户输入的字符只能是中文或英文
# 同理如果保存到硬盘的是Shift_JIS格式二进制,当初用户输入的字符只能是日文或英文……
# 如果我们输入的字符中包含多国字符,那么该如何处理?
# 多国字符—√—>内存(unicode格式的二进制)——X—>硬盘(GBK格式的二进制)
# 多国字符—√—>内存(unicode格式的二进制)——X—>硬盘(Shift_JIS格式的二进制)
# 多国字符—√—>内存(unicode格式的二进制)——√—>硬盘(???格式的二进制)
# 【2】解决办法(utf-8)
# 多国字符—√—>内存(unicode格式的二进制)——√—>硬盘(utf-8格式的二进制)
# 【3】utf8不够用
# 颜文字 ---> utf8mb4
# 【4】最后
# 随着时代的发展 可能 unicode 就被淘汰了 只剩下 utf8
【六】补充
#python2.x 文件头
# --*-- utf-8
当前文件编码强制使用utf8
# 不要随意修改自己文件的编码格式
# 默认的编码格式全都是UTF-8
# 如果修改了源文件的编码格式造成的后果就是数据找不回来了
![屏幕截图 2024-04-09 090030](D:\29期笔记\09\垃圾回收机制.assets\屏幕截图 2024-04-09 090030.png)
标签:栈区,字符,编码,二进制,回收,---,垃圾,机制,内存 From: https://www.cnblogs.com/yi416/p/18190495