内置方法补充以及序列模块初识
内置方法
__new__
在__init__之前,实例化的对象的第一步是__new__创建了一个空间
1 class Foo: 2 def __init__(self): #初始化方法 3 print('执行了init') 4 5 def __new__(cls, *args, **kwargs): #构造方法 6 object.__new__(cls) 7 print('执行了new') 8 return object.__new__(cls) 9 obj = Foo() 10 #执行了new 11 #执行了init
设计模式 常用的有23种 (始于java)
单例模式
一个类,只有一个实例的时候,用单例模式
1 class Foo: 2 __qwer = None 3 4 def __init__(self, name, age): #初始化方法 5 self.name = name 6 self.age = age 7 8 def __new__(cls, *args, **kwargs): #构造方法 9 if cls.__qwer is None: 10 cls.__qwer = object.__new__(cls) 11 return cls.__qwer 12 13 14 obj1 = Foo('wang', 18) 15 obj2 = Foo('rui', 20) 16 print(obj1.name, obj2.name) 17 #rui rui 18 #无论实例化多少个对象,他们的内存地址是相同的,也就是说结果是最后一个对象的属性
__del__
析构方法:在删除一个类创建的对象的时候会先触发__del__方法,在删除这个对象
1 class Foo: 2 def __init__(self, name, age): 3 self.name = name 4 self.age = age 5 self.file = open('file', mode='w') 6 7 def write(self): 8 self.file.write('qwerdf') 9 10 def __del__(self):#析构方法:删除类创建的对象时先执行这个方法,再删除对象 11 #做一些清理工作,比如文件的关闭,关闭网络链接,数据库的链接等 12 self.file.close() 13 print('执行了del') 14 15 16 f = Foo('wang', 18) 17 print(f) 18 #<__main__.Foo object at 0x00000248B55C0390>(对象的内存地址) 19 #执行了del
__len__
len() list,dict,set,str....
1 class Foo: 2 def __len__(self): 3 return 1 4 obj = Foo() 5 print(len(obj)) 6 #1
1 class NumberOfPeople: 2 def __init__(self, name, course): 3 self.name = name 4 self.course = course 5 self.students = [] 6 def __len__(self): 7 return len(self.students) 8 s1 = NumberOfPeople('终极一班','history') 9 s1.students.append('小明') 10 s1.students.append('小王') 11 print(len(s1)) #2 12 print(s1.__len__()) #2
__eq__
根据__eq__方法里的代码去判断两边是否相等
1 class Student: 2 def __init__(self, name, sex): 3 self.name = name 4 self.sex = sex 5 6 def __eq__(self, other): 7 return self.__dict__ == other.__dict__ 8 9 10 s1 = Student('小明', 'male') 11 s2 = Student('小明', 'male') 12 s3 = Student('小河', 'female') 13 print(s1 == s2) #True 14 print(s2 == s3) #False
__hash__
每次执行hash值都会变化
在一次执行的过程中对同一个值的hash总是不变的
字典为什么寻找快??
dic={'name':'wang','age':18,'sex':male}
字典在内存是如何存储的? 为什么字典的key必须可hash
会把字典的值转化成哈希值,然后把对应的哈希值存储在内存中,每个哈希值只有一个内存地址,所以每次寻找的时候会根据哈希值直接在内存地址中找
hash 算法
对于相同的值在一次程序的运行中是不会变化的
对于不同的值在一次程序的运行中总是不同的
set 的去重机制
对每一个元素进行hash,计算出一个内存地址
到这个内存地址上查看:
如果内存地址中没有这个值 就将这个值存在内存地址中
如果内存地址中有这个值 那么就判断两个值是否相等:如果相等,就舍弃后面的值。。如果不相等,就二次寻址再找一个新的内存地址存储这个值

1 class Staff: 2 def __init__(self,name,age,sex,dep): 3 self.name = name 4 self.age = age 5 self.sex = sex 6 self.dep = dep 7 def __hash__(self): 8 return hash(self.name+self.sex) 9 def __eq__(self, other): 10 if self.name == other.name and self.sex ==other.sex 11 return True 12 name_lst = ['zhao','qian','sun','li'] 13 obj_lst = [] 14 for i in range(100): 15 name = name_lst[i % 4] 16 obj = Staff(name,i,'male','history') 17 obj_lst.append(obj) 18 print(obj_lst) 19 ret = set(obj_lst) 20 print(ret) 21 for i in ret: 22 print(i.name,i.age)
模块
模块就是别人写好的功能放在一个文件里
内置模块:安装python解释器的时候一起装上的
第三方模块、扩展模块:需要自己安装
自定义模块:自己写的py文件
序列化模块
序列:列表、元组、字符串、bytes
序列化:把一个数据类型转化成字符串、bytes类型的过程就是序列化
序列化的理由:当你需要把一个数据类型存储在文件中
当你需要把一个数据类型需要网络传输的时候
1 import json 2 stu = {'name': '小明', 'sex': 'male'} 3 ret = json.dumps(stu) #序列化的过程 4 print(stu, type(stu)) 5 print(ret, type(ret)) 6 d = json.loads(ret) #反序列化的过程 7 print(d, type(d)) 8 #{'name': '小明', 'sex': 'male'} <class 'dict'> 9 #{"name": "\u5c0f\u660e", "sex": "male"} <class 'str'> 10 #{'name': '小明', 'sex': 'male'} <class 'dict'>
1 import json 2 lst = [1,2,3,4,'aaa','bbb'] 3 ret = json.dumps(lst) #序列化的过程 4 print(lst,type(lst)) 5 print(ret,type(ret)) 6 d = json.loads(ret) #反序列化的过程 7 print(d,type(d)) 8 #[1, 2, 3, 4, 'aaa', 'bbb'] <class 'list'> 9 #[1, 2, 3, 4, "aaa", "bbb"] <class 'str'> 10 #[1, 2, 3, 4, 'aaa', 'bbb'] <class 'list'>
1 import json 2 dic = {'name':'小明','sex':'male'} 3 str_dic1 = s= json.dumps(dic,ensure_ascii=False) 4 print(str_dic1) #{"name": "小明", "sex": "male"} 5 with open('json_file','w',encoding='utf-8')as f: 6 f.write(str_dic1) 7 with open('json_file','r',encoding='utf-8')as f: 8 content = f.read() 9 ret = json.loads(content) 10 print(ret['name']) #小明 11 #ensure_ascii = Falese是在文件中显示中文,原本的是ascii码
dump load 这两个方法是完全和文件打交道的
可以多次向文件dump,但是不能多次load
1 import json 2 dic = {'name':'小明','sex':'male'} 3 with open('json_file','w',encoding='utf-8')as f: 4 json.dump(dic,f,ensure_ascii =False) 5 with open('json_file','r',encoding='utf-8')as f: 6 dic = json.load(f) 7 print(dic,dic['name']) 8 #{'name': '小明', 'sex': 'male'} 小明
json 的优点:所有的语言都通用
json 的缺点:只支持非常少的数据类型
对数据类型的约束很苛刻,字典的key必须是字符串
只支持:数字、字符串、列表、字典
dumps(dic/list) dic/list---->str 序列化方法
loads(str) str--->dic/list 反序列化方法
dump(dic/list,f) dic/list--->文件 序列化方法
load(f) 文件--->dic/list 反序列方法 多次dump进入文件的数据load会报错
参数:ensure_ascii = False 希望序列化的中文能以中文的形式保存在文件中
json 格式化
1 rt json 2 date = {'username':['李华','二愣子'],'sex':'male','age':16} 3 json_dic2 = json.dumps(date,sort_keys=True,indent=4,separators=(',',':'),ensure_ascii=False) 4 print(json_dic2) 5 #{ 6 "age":16, 7 "sex":"male", 8 "username":[ 9 "李华", 10 "二愣子" 11 ] 12 }
pickle
与json类似
1 import pickle 2 class Sports: 3 def __init__(self,name,price): 4 self.name = name 5 self.price = price 6 basketball = Sports('basketball',111) 7 soccer = Sports('soccer',99) 8 ret = pickle.dumps(basketball) 9 print(type(ret)) #<class 'bytes'> 10 p = pickle.loads(ret) 11 print(p.name,p.price) #basketball 111 12 13 14 with open('pickle_file','wb')as f: 15 pickle.dump(basketball,f) #写入文件保存 16 with open('pickle_file','rb')as f: 17 sports = pickle.load(f) 18 print(sports.name) #basketball 取出
pickle:dump、load
操作文件必须以+b打开
在load的时候,如果这个要被load 的内容所在的类不在内存中,会报错
pickle 支持多次dump和多次load(需要异常处理)
1 #pickle 能不能多次 dump 2 def my_dump(course): 3 with open('pickle','ab') as f: 4 pickle.dump(course,f) 5 my_dump(python) 6 my_dump(linux) 7 my_dump(mysql) 8 9 with open('pickle','rb') as f: 10 while True: 11 try: 12 content = pickle.load(f) 13 print(content.name) 14 except EOFError: 15 break

浙公网安备 33010602011771号