内置方法补充以及序列模块初识

内置方法

__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
init,new执行顺序

设计模式   常用的有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
View Code
 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
__len__

__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
__eq__

__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)
100个员工选出名字和性别一样的

模块

模块就是别人写好的功能放在一个文件里

内置模块:安装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'}  小明
dump,load

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
多次dump,load

 

posted @ 2018-09-03 13:59  .why  阅读(230)  评论(0)    收藏  举报
Live2D