Python学习笔记-Day22-内置方法及序列化模块
内容大纲
一、内置方法__new__/__del__/__len__/__hash__/__eq__
二、序列化模块pickle和json
一、内置方法
1、__new__:构造方法
在执行__init__之前,类会调用ibject中的__new__方法创建一个对象空间
class Foo: def __init__(self): print('init') def __new__(cls, *args, **kwargs): print('new') return object.__new__(cls) f = Foo() 结果:init new
重要应用:单例模式
class Foo: __instance = None def __init__(self,name,age): self.name = name self.age = age self.lst = [name] def __new__(cls, *args, **kwargs): if cls.__instance is None: cls.__instance = object.__new__(cls) return cls.__instance obj1 = Foo('小明',23) obj2 = Foo('小红',24) print(obj1.name,obj1.age) # 小红 24 print(obj1.lst) # ['小红']
2、__del__:析构方法,当对象在内存中被释放的时候,会主动触发这个方法,当对象被删除的时候,会先触发这个方法在删除对象,这个方法通常用于关闭文件,归还系统资源等,到程序结束总会执行这个方法
class Foo: def __del__(self): print('执行我啦') obj = Foo() del obj print('结束') 结果:执行我啦 结束
3、__len__:可以使用len()函数计算对象的长度
class Class: def __init__(self,course): self.course = course self.student = [] def __len__(self): return len(self.student) python = Class('python') python.student.append('小明') python.student.append('小红') python.student.append('小黑') print(len(python)) # 3
4、__eq__:可根据eq中的条件判断两个对象是否相等
class Foo: def __init__(self,name,age): self.name = name self.age = age def __eq__(self, other): if self.name == other.name: return True else: return False obj1 = Foo('小明',23) obj2 = Foo('小红',23) obj3 = Foo('小明',24) print(obj1==obj2) # False print(obj1==obj3) # True
5、__hash__:根据自定义的条件计算对象的哈希值
class Foo: pass obj = Foo() print(hash(obj)) #-9223371856450203262 class Foo: def __hash__(self): return hash('foo') obj = Foo() print(hash(obj)) #-3494245336101080890
哈希算法的特点:
1、同一个程序中,相同的值的哈希值是相同的
2、同一个程序中,不同的值的哈希值总是不同的(也有一些例外)
字典寻址快的原因:首先计算键的hash值,得出内存地址,根据内存地址找到value
set的去重原理:① 首先计算元素的哈希值,得到内存地址
② 到这个内存地址上去看,如果没有值,就把这个值放到这个内存地址上;如果有值,判断两个值是否相等,相等的话就丢弃后一个值,不想等的话进行二次寻址找另一块内存去存这个值
例题:100个员工的去重,姓名和性别相同就是同一个员工
class Staff: def __init__(self,name,age,sex,department,): self.name = name self.age = age self.sex = sex self.department = department def __eq__(self, other): if self.name == other.name and self.sex == other.sex: return True def __hash__(self): return hash(self.name + self.sex) name_lst = ['小明','小红','小黑','小白'] lst = [] for i in range(100): name = name_lst[i%4] obj = Staff(name,i,'male','python') lst.append(obj) set1 = set(lst) for i in set1: print(i.name,i.age) #结果: 小明 0 小黑 2 小红 1 小白 3
二、序列化模块
什么是模块?
别人写好的功能封装在一个文件里
内置模块:安装python解释器的时候自动安装上的
第三方模块、扩展模块:使用时需要自己安装
自定义模块:自己写的py文件
什么是序列?
list、dict、str、bytes就是序列
什么是序列化?
将一个数据类型类型转化成str或bytes类型就是序列化
为什么要序列化?
当你需要将一种数据类型进行存储或网络传输的时候,需要转化成str或bytes类型
json和pickle模块就是专门将其他数据类型转化成字符串或bytes类型进行存储和网络传输用
1、json:
json的特点:① 能够在所有语言中通用
② 能转化的类型有限,只能转化列表、字典、字符串、数字(元组会被转化成列表)
③ 对字典的要求很高,键必须是字符串类型,且反序列化的时候必须不能有单引号,全部变成双引号
json的用法(4种):
json.dumps(dict/list):序列化方法,将dict类型或list类型转化成字符串类型
json.loads(str):反序列化方法,将str类型重新转化成dict/list
json.dump(序列,f):序列化方法,将dict/list ---->str并写入文件
json.load(f):反序列化方法,将文件中的字符串类型的数据重新转化成dict/list
举例:
import json stu={'name':'小红','age':23} ret = json.dumps(stu,ensure_ascii=False) # ensure_ascii=False可以显示中文 print(ret,type(ret)) # {"name": "小红", "age": 23} <class 'str'> dic = json.loads(ret) print(dic,type(dic)) # {'name': '小红', 'age': 23} <class 'dict'>
import json stu={'name':'小红','age':23} with open('file',mode='w',encoding='utf-8') as f: json.dump(stu,f,ensure_ascii=False) with open('file',encoding='utf-8') as f1: ret = json.load(f1) print(ret) # {'name': '小红', 'age': 23}
注意:多次进行dump,load时会报错
json的格式化:可以百度json的格式化工具
import json data = {'username': ['李华', '二愣子'], 'sex': 'male', 'age': 16} ret = json.dumps(data,sort_keys=True,indent=4,separators=(',',':'),ensure_ascii=False) print(ret) # { # "age":16, # "sex":"male", # "username":[ # "李华", # "二愣子" # ] # }
2、pickle
pickle的特点:
① 只能在python中使用
② 可以序列化任意的数据类型
③ 进行文件操作时必须是‘+b‘的模式
④ load对象的时候,对象所属的类必须在内存中
⑤ 支持多次dump和多次load,但是需要异常处理。except EOFError
举例:
# 序列化和反序列化一个字典 import pickle stu={'name':'小红','age':23} str1 = pickle.dumps(stu) print(str1,type(str1)) #是个bytes类型的数据 dic = pickle.loads(str1) print(dic) # {'name': '小红', 'age': 23} # 序列化和反序列化一个对象 class Course: def __init__(self,name,age): self.name = name self.age = age python = Course('python',12345) ret = pickle.dumps(python) print(ret) obj = pickle.loads(ret) print(obj.name) # python
import pickle class Course: def __init__(self,name,age): self.name = name self.age = age python = Course('python',12345) linux = Course('linux',1225) java = Course('java',3433) with open('file3','ab') as f: pickle.dump(python,f) pickle.dump(linux,f) pickle.dump(java,f) with open('file3','rb') as f1: while True: try: obj = pickle.load(f1) name = obj.name print(name) except EOFError: break