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

 

posted @ 2018-09-13 15:40  whuitian  阅读(99)  评论(0编辑  收藏  举报