【2022-06-28】字符编码与文件操作简介
字符编码与文件操作简介
垃圾回收机制
-
什么是垃圾回收机制
垃圾回收机制(简称GC)是python解释器自带的一种机制,专门用来回收不可用的数据值所占用的内存空间
-
垃圾回收机制的原理
Python 的GC模块主要运用了引用计数来跟踪和回收垃圾;通过“标记-清除”解决容器对象可能产生的循环引用问题;通过分代回收以空间换时间进一步提高垃圾回收的效率。
-
引用计数
为每一个对象维护一个引用计数器,当一个对象的引用被创建或者复制时,(对象的引用)计数器+1,当一个对象的引用被销毁时,计数器的值-1,当计数器的值为0时,就意味着对象已经再没有被使用了,可以将其内存释放掉。
比如:a = 66 # 数据值66绑定给了变量名a,这个就称之为引用计数为1 增加引用计数: a = 66 # 此时的引用计数为1 b = a # 把a的内存地址给了b,此时a和b都绑定了66,所以数据值66的引用计数就为2 减少引用计数: a = 20 # 变量名a先与数据值66解除绑定,数据值66的引用计数为1 del b # del的意思就是解除变量名b与数据值66的关联关系,这个时候,数据值66的引用计数为0此外,引用计数还存在着一个巨大的缺陷就是循环引用,类似于while循环里的死循环,它会导致数据值不再被任何的变量名绑定,但是数据值的引用计数不会为0 # 如下我们定义了两个列表,简称列表1与列表2,变量名l1指向列表1,变量名l2指向列表2 # l1=['123'] # 列表1被引用一次,列表1的引用计数变为1 # l2=['321'] # 列表2被引用一次,列表2的引用计数变为1 # l1.append(l2) # 把列表2追加到l1中作为第二个元素,列表2的引用计数变为2 # l2.append(l1) # 把列表1追加到l2中作为第二个元素,列表1的引用计数变为2 # l1与l2之间有相互引用 # l1 = ['123'的内存地址,列表2的内存地址] # l2 = ['321'的内存地址,列表1的内存地址] # l1 ['123', ['321', [...]]] # l2 ['321', ['123', [...]]] # del l1 # 列表1的引用计数减1,列表1的引用计数变为1 # del l2 # 列表2的引用计数减1,列表2的引用计数变为1此时,只剩下列表1与列表2之间的相互引用,两个列表的引用计数均不为0,但两个列表不再被任何其他对象关联,没有任何人可以再引用到它们,所以它俩占用内存空间应该被回收,但由于相互引用的存在,每一个对象的引用计数都不为0,因此这些对象所占用的内存永远不会被释放,所以循环引用是致命的,这与手动进行内存管理所产生的内存泄露毫无区别。所以Python引入了“标记-清除” 与“分代回收”来分别解决引用计数的循环引用与效率低的问题
-
标记清除
“标记-清除”的出现打破了循环引用,它只关注那些可能会产生循环引用的对象,Python中的循环引用总是发生在容器container对象之间,也就是能够在内部持有其他对象的对象(比如:list、dict、class等)。这也使得该方法带来的开销只依赖于容器对象的数量。
-
分代回收
在检查数据值的过程中,多次扫描都没有被回收的数据值,GC机制就会认为,该数据值是常用数据值,存活时间越长的数据值,就越不可能是垃圾,于是便减少了对它的垃圾收集频率
字符编码简介
-
什么是字符编码
字符编码,编码的意思是指将数据通过一定方式表达或储存。所以字符编码就是字符的表现、储存方式,也就是字符集的实现方式。
-
编码与解码
我们计算机中存储的信息都是用二进制数来表示的,像我们在电脑屏幕上看到的数字,文本文件,标点符号等等都是二进制数转换之后的结果。按照某种规则,将字符存储到计算机中,称之为编码。反之,将存储在计算机中的二级制数按照某种规则解析显示出来,称之为解码。
字符编码发展史
1.一家独大
计算机是有美国人发明的 美国人需要让计算机识别英文字符
ps:英文所有的字符加起来不超过127个(2的七次方) 但是美国人考虑到后续可能出现新的字符所以加了一位以备不时之需(2的八次方)
ASCII码:内部只记录了英文字符与数字的对应关系
1bytes来存储字符
A-Z 65-90
a-z 97-122
ps:此时的计算机只能识别英文 不识别其他文字
2.群雄割据
中国
需要让计算机识别中文 需要开发一套中文的编码表
GBK码:内部记录了中文字符、英文字符与数字的对应关系
2bytes起步存储中文(遇到生僻字使用更多字节)
1bytes存储英文
韩国
需要让计算机识别韩文 需要开发一套韩文的编码表
Euc_kr码:内部记录了韩文字符、英文字符与数字的对应关系
日本
需要让计算机识别日文 需要开发一套日文的编码表
shift_JIS码:内部记录了日文字符、英文字符与数字的对应关系
ps:此时的各国计算机文本文件无法直接交互 会出现乱码的情况
3.天下一统
万国码(unicode):兼容万国字符
所有的字符全部使用2bytes起步存储
utf家族(针对unicode的优化版本)>>>:utf8
英文还是采用1bytes
其他统一采用3bytes
ps:内存使用unicode 硬盘使用utf8
文件操作简介
-
什么是文件
文件是操作系统为用户或应用程序提供的一个读写硬盘的虚拟单位。文件的操作是基于文件,即文件的操作核心就是:读和写。也就是说只要我们想要操作文件就要向操作系统发起请求,然后由操作系统将用户或应用程序对文件的读写操作转换为集体的硬盘指令,来读取数据
-
为什么要有文件
内存是无法永久保存数据的,如果出现意外断电的情况,那么很有可能会造成数据的损坏与丢失,但是我们可以通过把文件保存在硬盘中,而操作文件就可以实现对硬件的操作
-
如何使用文件
比如从硬盘中读取数据,打开一个文件夹,我们需要向操作系统发起请求,要求操作系统打开文件,占用操作系统资源。在python中使用open()方法可以打开某个具体的文件,open()方法内写入文件的路径即可。
open(r'D:\aaa\bbb\1.txt) 针对文件路径需要注意 可能存在特殊含义(字母与撬棍的组合,在字符串的前面加字母r即可取消特殊含义
课题演练
# 1.统计列表中每个数据值出现的次数并组织成字典展示
# eg: l1 = ['jason','jason','kevin','oscar']
# 结果:{'jason':2,'kevin':1,'oscar':1}
# 真实数据
# l1 = ['jason','jason','kevin','oscar','kevin','tony','kevin']
# l1 = ['jason', 'jason', 'kevin', 'oscar', 'kevin', 'tony', 'kevin']
# # 1.先定义一个空列表
# new_list = {}
# # 2.统计列表中每个数据出现的次数,并转换成字典的K:V键值对形式
# for i in l1: # 循环打印列表l1里边的值并赋值给变量名i
# if i not in new_list: # 如果i不在我这个新的列表里
# new_list[i] = 1 #
# else:
# new_list[i] += 1 # 将i的值+1后重新赋值给新的列表new_list
# print(new_list) # {'jason': 2, 'kevin': 3, 'oscar': 1, 'tony': 1}
# 2.编写员工管理系统,并使用函数进行封装
# 1.添加员工信息
# 2.修改员工薪资
# 3.查看指定员工
# 4.查看所有员工
# 5.删除员工数据
# 提示:用户数据有编号、姓名、年龄、岗位、薪资
# 数据格式采用字典:思考如何精准定位具体数据>>>:用户编号的作用
# 使用函数封装
def staff_system():
# 1.先定义一个存放用户数据信息的空字典
data_dict = {}
# 2.搭建功能框架
while True:
print("""
1.添加员工信息
2.修改员工薪资
3.查看指定员工
4.查看所有员工
5.删除员工数据
""")
# 3.获取用户输入的功能编号
function_id = input('请输入您想要执行的功能编号>>>:').strip()
# 4.判断用户想要输入的功能编号
if function_id == '1':
# 5.获取员工编号
emp_id = input('请输入员工的编号>>>:').strip()
# 6.判断该员工编号是否已经存在
if emp_id in data_dict:
print('该员工编号已存在')
continue
# 7.获取员工的其他信息
user_name = input('请输入员工姓名>>>:').strip()
user_age = input('请输入员工年龄>>>:').strip()
user_job = input('请输入员工岗位>>>:').strip()
user_salary = input('请输入员工薪资>>>>:').strip()
# 8.创建一个存放员工数据的小字典
user_info = {}
# 9.将员工信息全部放入小字典
user_info['emp_id'] = emp_id
user_info['user_name'] = user_name
user_info['user_age'] = user_age
user_info['user_job'] = user_job
user_info['user_salary'] = user_salary
# 10.将员工数据小字典放入大字典里
data_dict[emp_id] = user_info
elif function_id == '2':
# 1.获取员工编号
emp_id = input('请输入员工编号>>>:').strip()
# 2.判断当前员工编号是否存在
if emp_id not in data_dict:
print('当前员工不存在,无法进行修改')
continue
# 3.根据员工编号获取员工的详细信息
emp_data = data_dict.get(emp_id)
# 4.获取该员工新的薪资
new_salary = input('请输入该员工新的薪资>>>:').strip()
# 5.修改员工小字典里对应的数据
emp_data['user_salary'] = new_salary
# 6.将修改后的小字典重新赋值给大字典
data_dict[emp_id] = emp_data
# 7.提示信息:员工薪资已修改
print(f'员工编号:{emp_id}, 员工姓名:{emp_data.get("user_name")}薪资修改成功')
elif function_id == '3':
# 1.获取员工编号
emp_id = input('请输入员工编号>>>:').strip()
# 2.判断该员工编号是否存在
if emp_id not in data_dict:
print('该员工编号不存在,请重新输入')
continue
# 3.根据员工编号获取员工数据
emp_data = data_dict.get(emp_id)
# 4.格式化输出员工数据
print(f"""
---------------emp_info---------------
编号:{emp_data.get('emp_id')}
姓名:{emp_data.get('user_name')}
年龄:{emp_data.get('user_age')}
岗位:{emp_data.get('user_job')}
薪资:{emp_data.get('user_salary')}
--------------------------------------
""")
elif function_id == '4':
# 1.获取所有的员工小字典
all_emp_data = data_dict.values()
# 2.循环获取每一个员工数据字典
for emp_data in all_emp_data:
# 3.格式化输出员工信息
print(f"""
---------------emp_info---------------
编号:{emp_data.get('emp_id')}
姓名:{emp_data.get('user_name')}
年龄:{emp_data.get('user_age')}
岗位:{emp_data.get('user_job')}
薪资:{emp_data.get('user_salary')}
--------------------------------------
""")
elif function_id == '5':
# 1.获取想要删除的员工编号
delete_id = input('请输入您想要删除的员工编号>>>:').strip()
# 2.判断该员工编号是否存在
if delete_id not in data_dict:
print('该员工编号不存在')
continue
# 3.根据员工编号删除对应的键值对
data_dict.pop(delete_id)
# 4.提示信息
print(f'员工编号{delete_id}删除成功')
else:
print('请输入正确的编号功能')
staff_system()

浙公网安备 33010602011771号