摘要:__new__    __del__   __call__   __len__     __eq__    __hash__
import json 序列化模块
import pickle 序列化模块 补充:
现在我们都应该知道一个对象的类型(type)就是创建这个对象的类,
而类也是被创建出来的,那么类的类型(type)也是创建这个类的类型,
创建类的是type元类,所以没有指定mateclass的类的type就是type,
指定了mateclass的类的type就是指定的mateclass的值。 例如:
from abc import ABCMeta class A:
pass class B:
pass class C(metaclass=ABCMeta):
pass print(type(A)) # <class 'type'>
print(type(B)) # <class 'type'>
print(type(C)) # <class 'abc.ABCMeta'> 一、内置方法
0、__dict__ 方法
class Foo:
  f1 = "类属性"
  
  def __init__(self):
    self.obj = "对象属性" # 查看类的__dict__和对象的__dict__
obj = Foo()
print(Foo.__dict__) # {'__model__': '__main__', 'f1': '类属性', '__init__': <function Foo.__init__ at 0x00000018C6D3D59D8> ....}
print(obj.__dict__) # {'obj': '对象属性'}
由此可以看出:类的__dict__会把类的所有属性对应的值和方法的地址以字典的形式打印出来
       对象的__dict__只把对象的属性以字典的形式打印出来,即只打印实例化对象时候__init__里面初始化的值
class BaseResponse(object):

    def __init__(self):
self.code = None
self.data = None
self.error = None @property
def dict(self):
return self.__dict__ # 这样构建的类,在写接口的时候就不需要频繁构建字典了
# 例如:返回错误的信息
res = BaseResponse()
res.code = 500 # 错误状态码
res.error = "错误的信息"
print(res.dict) # 在接口中实际上是 return Response(res.dict) # 返回成功处理的数据
res = BaseResponse()
res.code = 200
res.data = {'成功返回的数据': 'xxxx'}
print(res.dict) # 在接口中实际上是 return Response(res.dict)

应用于接口


1、__new__  构造方法
__new__:在__init__执行之前,实例化对象的第一步是__new__创建一个对象空间。 继承自object的新式类才有__new__
__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供,
__new__必须要有返回值,返回的是实例化出来的实例,
可以return父类__new__出来的实例,或者直接是object的__new__出来的实例,
但是如果__new__没有正确返回当前类cls的实例,那__init__是不会被调用的,即使是父类的实例也不行。
return的类是谁,就创建谁的对象,但是在本类中如果return的不是本类的对象,那么不会执行__init__。
# 正常的写法:
class Father:
def __init__(self):
print('执行了init') def __new__(cls, *args, **kwargs):
print('执行了new')
return object.__new__(cls)
# return super().__new__(cls) f = Father() # 执行了new 执行了init # 不return本类的对象
class A:
name = 'a'
def __init__(self):
print("A--->init") class B:
name = 'b'
def __init__(self):
print("B--->init") def __new__(cls):
print("new %s" % cls)
# return object.__new__(cls) #正常返回当前类的实例,会执行当前类的init
# return super().__new__(cls) # 整个结果:
# new <class '__main__.B'>
# B--->init
# <class '__main__.B'>
# b # return object.__new__(A) # 返回A的实例,当前类和A的init都不会执行
# 整个结果:
# new <class '__main__.B'>
# <class '__main__.A'>
b = B() # a
print(type(b))
print(b.name) 单例模式:一个类只有一个实例的时候
class Singleton:
__instance = None
def __init__(self,name,age):
self.name = name
self.age = age def __new__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = object.__new__(cls)
return cls.__instance f1 = Singleton('小宁',18)
print(f1) # <__main__.Singleton object at 0x000001ECCB1FFA90> f2 = Singleton('小白',25)
print(f2) # <__main__.Singleton object at 0x000001ECCB1FFA90> 都是第一次创建的f1的地址 print(f1.name,f1.age) # 小白 25
print(f2.name,f2.age) # 小白 25 2、__del__ 析构方法
析构方法 : 在删除这个类创建的对象的时候会先触发这个方法,再删除对象,
方法内应该做一些清理工作,比如说关闭文件,关闭网络的链接,数据库的链接 class Father:
def __init__(self):
self.file = open('file',encoding='utf-8',mode='w') def My_write(self):
self.file.write('哈哈哈') def __del__(self):
self.file.close()
print('执行了del') f = Father()
del f # 执行了del
注意:重写__del__后,即使不写 def f 在函数执行完毕后,也会自动执行__del__方法 3、__call__
__call__()的作用是使实例(对象)能够像函数一样被调用,同时不影响实例本身的生命周期(__call__()不影响一个实例的构造和析构)。但是__call__()可以用来改变实例的内部成员的值。
class A:
def __init__(self,x,y):
self.x = x
self.y = y def __call__(self,a,b):
self.x = a
self.y = b a = A(1,2)
print(a.x,a.y) # 1 2 a(3,4)
print(a.x,a.y) # 3 4

4、__len__

len()           # 内置函数len可以接收的数据类型:list dict set str tuple
print('__len__' in dir(list)) # True
print('__len__' in dir(dict)) # True
print('__len__' in dir(set)) # True
print('__len__' in dir(tuple)) # True
print('__len__' in dir(str)) # True print('__len__' in dir(int)) # False
print('__len__' in dir(float)) # False # 从上面可以看出,能使用内置函数len的数据类型,内部都有__len__方法
# 之前说过我们常用的数据类型,其实也是对象,那么可以得出结论:
# 只要类中有__len__方法,那么这个类的对象就可以使用内置函数len class A:
def __len__(self):
return 1
a = A()
print(len(a)) # 1 值是__len__的返回值 class Father:
def __init__(self,s):
self.s = s def __len__(self):
return len(self.s) f = Father('你好啊')
print(len(f)) # 5、__eq__ :重写了类的 == 方法,遇到 == 运算符则自动触发
默认的__eq__不重写的话,比较的是两个对象的内存地址是否相同: class Staff:
def __init__(self,name,sex):
self.name = name
self.sex = sex s1 = Staff('小明',18)
s2 = Staff('小明',18)
s3 = Staff('小东',18) print(s1==s2) # False
print(s1==s3) # False 可以自己重写,让其比较值是否相等
class Staff:
def __init__(self,name,sex):
self.name = name
self.sex = sex def __eq__(self, other):
return self.__dict__ == other.__dict__ #对象的所有内容相同,则认为值相同 s1 = Staff('小明',18)
s2 = Staff('小明',18)
s3 = Staff('小东',18) print(s1==s2) # True
print(s1==s3) # False 6、__hash__
类的对象可以哈希
class Foo():
pass obj1 = Foo()
obj2 = Foo()
print(hash(obj1)) # 内存地址 97649779257
print(hash(obj2)) # 内存地址 97649779271 哈希算法:
1.每次执行hash值都会变化(因为会根据地址进行哈希)
2.但是在一次执行的过程中对同一个值的hash结果总是不变的
3.对于相同的值在一次程序的运行中是不会变化的
4.对于不同的值在一次程序的运行中总是不同的 字典为什么寻址快
因为:
  字典的键是不可变的数据类型,所以是可哈希的,
  字典在存入内存的时候会将你的所有的key先进行哈希,再将哈希值存入内存中,
  这样在查询的时候可以根据哈希值直接就可以找到,所以查询速度很快! set的去重机制
1.对每一个元素进行hash计算出一个地址
2.到这个地址对应的内存上查看
如果这块内存中没有值
将这个元素存到对应的内存地址上
如果这块内存中已经有值
判断这两个值是否相等
如果相等,就舍弃后面的值
如果不相等,就二次寻址再找一个新的空间来存储这个值 例如:100个对象,如果水果名相同的就只留一个
class Fruit:
def __init__(self,name,price):
self.name = name
self.price = price def __hash__(self):
return hash(self.name) def __eq__(self, other):
return self.name == other.name obj_lst = []
name_lst = ['苹果','香蕉','葡萄','榴莲']
for i in range(100):
name = name_lst[i % 4]
obj = Fruit(name,i)
obj_lst.append(obj)

#利用set的去重机制
ret = set(obj_lst) # 1、set对每一个元素进行hash计算出一个地址(此时触发__hash__)
# 2、查看每个地址的值是否相等(此时触发__eq__),相等的,set内部会自动去重。 for i in ret:
print(i.name,i.price) 二、序列化模块
模块:别人写好的功能放在一个文件里
内置模块 : 安装python解释器的时候一起装上的
第三方模块、扩展模块 :需要自己安装
自定义模块 : 你写的py文件 序列化模块
什么叫序列化
把一个数据类型转换成字符串、byets类型的过程就是序列化 为什么要把一个数据类型序列化?
{'name':'小明','sex':'male'}
当你需要把一个数据类型存储在文件中
当你需要把一个数据类型通过网络传输的时候 1、json序列化模块(换成字符串类型)
json的优点
所有的语言都通用,可以跨平台或跨语言进行数据交互
把数据类型(字典,列表)转成字符串形式,可以直接读写文件
转成的字符串都是以双引号的形式 缺点
只支持非常少的数据类型
只支持元组(会转成列表)、数字、字符串、列表、字典
应用场景
在网络操作中,以及多语言环境中,要传递字典、数字、字符串、列表等简单的数据类型的时候使用
对数据类型的约束很苛刻
字典的key必须是字符串或数字,但是如果key是数字,则会把数字转成字符串作为key
中文的值dumps后是字节形式的字符串 序列化:
dumps(dic/list) dic/list --> str 序列化方法
loads(str) str --> dic/list 反序列化方法
dump(dic/lst,f) dic/list --> 文件 序列化方法
load(f) 文件 --> dic/list 反序列化方法 多次dump进入文件中的数据load会报错
参数:ensure_ascii=False 希望序列化的中文能以中文的形式被显示并且写到文件中 import json
1-1、字典:
dic = {'name':'小明','sex':'male'}
ret = json.dumps(dic) # 序列化的过程:字典--->字符串
print(dic,type(dic)) # {'name': '小明', 'sex': 'male'} <class 'dict'>
print(ret,type(ret)) # {"name": "\u5c0f\u660e", "sex": "male"} <class 'str'> d = json.loads(ret) # 反序列化:字符串--->字典
print(d,type(d)) # {'name': '小明', 'sex': 'male'} <class 'dict'> 1-2、列表:
lst = [1,2,3,4,'aaa','bbb']
ret = json.dumps(lst) # 序列化的过程:列表--->字符串
print(lst,type(lst)) # [1, 2, 3, 4, 'aaa', 'bbb'] <class 'list'>
print(ret,type(ret)) # [1, 2, 3, 4, "aaa", "bbb"] <class 'str'> l = json.loads(ret) # 反序列化的过程:字符串--->列表
print(l,type(l)) # [1, 2, 3, 4, 'aaa', 'bbb'] <class 'list'> 1-3、元组:会被转成列表的形式,且转不回来
t1 = (1,2)
ret = json.dumps(t1)
print(ret,type(ret)) # [1, 2] <class 'str'> t2 = json.loads(ret)
print(t2,type(t2)) # [1, 2] <class 'list'> 1-4、key为数字的字典:会把数字转成字符串作为key,且转不回来
dic = {'name':'小明',1:(1,2)}
ret = json.dumps(dic)
print(dic,type(dic)) # {'name': '小明', 1: (1, 2)} <class 'dict'>
print(ret,type(ret)) # {"name": "\u5c0f\u660e", "1": [1, 2]} <class 'str'> d = json.loads(ret)
print(d,type(d)) # {'name': '小明', '1': [1, 2]} <class 'dict'> 1-5、单独的数字:无异常
a = 10
b = json.dumps(a)
print(b,type(b)) # 10 <class 'str'> ret = json.loads(b)
print(ret,type(ret)) # 10 <class 'int'> 1-6、字符串(等于没转,只是把单引号变成双引号):
a = 'aa'
b = json.dumps(a)
print(b,type(b)) # "aa" <class 'str'> ret = json.loads(b)
print(ret,type(ret)) # aa <class 'str'> 1-7、loads可以单独使用:
ret = '{"name": "hello", "sex": "male"}'
dic2 = json.loads(ret) # 反序列化
print(dic2,type(dic2)) # {'name': 'hello', 'sex': 'male'} <class 'dict'> 1-8、dumps的参数ensure_ascii:把中文正常显示出来,并不是字节形式
dic = {'name': '小明', 'sex': 'male'}
str1_dic = json.dumps(dic,ensure_ascii=False)
str2_dic = json.dumps(dic)
print(str1_dic) # {"name": "小明", "sex": "male"}
print(str2_dic) # {"name": "\u5c0f\u660e", "sex": "male"} 1-9、json读写文件:
普通的读写,dumps loads
简洁读写 dump load 普通的读写:写入时先dumps,读出时先loads
dic = {'name': '小明', 'sex': 'male'}
str = json.dumps(dic)
with open('json_file','w',encoding='utf-8') as f:
f.write(str) with open('json_file',encoding='utf-8',mode='r') as f:
content = f.read()
ret = json.loads(content)
print(ret) 读写方法:dump load,这两个方法是完全和文件打交道的
dump(内容,文件句柄,ensure_ascii) dic = {'name': '小明', 'sex': 'male'}
with open('json_file',encoding='utf-8',mode='w') as f:
json.dump(dic,f,ensure_ascii=False) load(文件句柄) with open('json_file',encoding='utf-8',mode='r') as f:
dic = json.load(f)
print(dic) 1-10、可以多次向一个文件中dump,但是不能多次load。
dic = {'name': '小明', 'sex': 'male'}
with open('json_file',encoding='utf-8',mode='w') as f:
json.dump(dic,f,ensure_ascii=False)
json.dump(dic,f,ensure_ascii=False)
json.dump(dic,f,ensure_ascii=False) # 可以多次dump with open('json_file',encoding='utf-8',mode='r') as f:
dic = json.load(f) # 但是不能多次load。
print(dic) 总结:
一次dump,可以用load或者loads读出内容
多次dump,无论是load或者loads都会报错(但是其实可以用for循环读出) 1-11、多次向一个文件写入
def my_dumps(dic):
with open('json_file',encoding='utf-8',mode='a') as f:
dic_str = json.dumps(dic)
f.write(dic_str + '\n')
dic1 = {'name':'小明','sex':'male'}
dic2 = {'name':'晓东','sex':'male'}
dic3 = {'name':'李三','sex':'male'}
my_dumps(dic1)
my_dumps(dic2)
my_dumps(dic3) with open('json_file',encoding='utf-8',mode='r') as f:
for line in f:
dic = json.loads(line.strip())
print(dic) 1-12、json格式化
import json # dumps
data = {'name':['小明','张三'],'sex':'male','age':19}
json_dic = json.dumps(data,sort_keys=True,indent=4,separators=(',',':'),ensure_ascii=False)
print(json_dic) # dump
data = {'name':['小明','张三'],'sex':'male','age':19}
with open('json_file',encoding='utf-8',mode='w') as f:
  json.dump(data,f,sort_keys=True,indent=4,ensure_ascii=False)
# sort_keys=True:按照ASCII排序(a-z)
# indent=4:设置缩进格数,每次换行空四个格
# separators=(',',':'):设置分隔符,假如在dic = {'a': 1, 'b': 2, 'c': 3}这行代码里可以看到冒号和逗号后面都带了个空格,
# 这也是因为Python的默认格式也是如此,如果不想后面带有空格输出,那就可以设置成separators=(',', ':'),
# 如果想保持原样,可以写成separators=(', ', ': ')。
# ensure_ascii=False:中文以中文形式显示 2、pickle序列化模块(换成byets类型):
应用场景:
pickle模块实现了基本的数据序列和反序列化,和json的功能类似。
通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储,也可以简单的将字符进行序列化
通过pickle模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象,也可以将字符进行反序列化。
和json不同的是:json 更适合跨语言 可以处理字符串,基本数据类型;pickle是python专有,更适合处理复杂类型的序列化 具体应用:
dumps 和loads 用于python对象和字符串间的序列化和反序列化
dumps 和json.dumps功能一样,但是以字节对象形式返回封装的对象
loads和json.loads功能一样,从字节对象中读取被封装的对象,并返回 2-1、dumps、loads
import pickle dic = {'name':'小明','sex':'male',1:('a','b')}
ret = pickle.dumps(dic) # 序列化的过程:字典--->bytes
print(ret,type(ret)) #b'\x80\x03}q\x00(X\x04\x00\'<class 'bytes'> dic2 = pickle.loads(ret) # 反序列化:bytes--->字典
print(dic2,type(dic2)) # {'name': '小明', 'sex': 'male', 1: ('a', 'b')} <class 'dict'> class Course():
def __init__(self,name):
self.name = name python = Course('python')
ret = pickle.dumps(python) # 序列化的过程:对象--->bytes
print(ret) # b'\x80\x03c__main__\nCourse\nq\x00)\x00pythonq\x04sb.' p = pickle.loads(ret) # 反序列化的过程:bytes--->对象
print(p) # <__main__.Course object at 0x0000028FE9583AC8>
print(p.name) # python # 读写文件的方法dump和load
with open('pickle',mode='wb') as f:
pickle.dump(python,f) with open('pickle',mode='rb') as f1:
print(pickle.load(f1)) pickle:dump、load
操作文件文件必须以b模式进行操作
在load的时候 如果这个要被load的内容所在的类不在内存中,会报错 *****
pickle支持多次dump和多次load(需要异常处理) import pickle
class Fruit:
def __init__(self,name):
self.name = name apple = Fruit('苹果')
banana = Fruit('香蕉') def my_dump(fruit):
with open('pickle','ab') as f:
pickle.dump(fruit,f)
my_dump(apple)
my_dump(banana) with open('pickle','rb') as f:
while True:
try:
content = pickle.load(f)
print(content.name)
except EOFError:
break

python之序列化模块、双下方法(dict call new del len eq hash)和单例模式的更多相关文章

  1. Python面向对象之反射,双下方法

    一. 反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序 ...

  2. Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究

    Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究 一丶反射 什么是反射: ​ 反射的概念是由Smith在1982年首次提出的 ...

  3. Python面向对象06 /元类type、反射、函数与类的区别、特殊的双下方法

    Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 目录 Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 1. 元类type 2. 反射 3 ...

  4. python 面向对象专题(六):元类type、反射、函数与类的区别、特殊的双下方法

    目录 Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 1. 元类type 2. 反射 3. 函数与类的区别 4. 特殊的双下方法 1. 元类type type:获取对象 ...

  5. 百万年薪python之路 -- 面向对象之 反射,双下方法

    面向对象之 反射,双下方法 1. 反射 计算机科学领域主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省) python面向对象中的反射:通过字符串的形式操作对象相关的属性.python ...

  6. Python反射和内置方法(双下方法)

    Python反射和内置方法(双下方法) 一.反射 什么是反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发 ...

  7. Python 入门 之 双下方法

    Python 入门 之 双下方法 1.双下方法 ​ 定义:双下方法是特殊方法,它是解释器提供的 由双下划线加方法名加双下划线 方法名的具有特殊意义的方法,双下方法主要是python源码程序员使用的,我 ...

  8. python之面向对象函数与方法,反射,双下方法

    一.函数和方法 1.函数和方法的区别 函数: 全都是显性传参,手动传参,与对象无关 方法: 存在隐性传参,与对象有关 1.1通过函数名可以判断 len()就是函数 str.count()就是方法 de ...

  9. python之路-双下方法

    双下方法 定义: 双下方法是特殊方法,他是解释器提供的,由双下线加方法名加双下划线 __方法名__具有特殊意义的方法 双下方法主要是Python源码程序员使用的,元编程 我们在开发中尽量不要使用双下方 ...

随机推荐

  1. 【20190304】JavaScript-知识点总结:Set,异或

    ES6新特性:Set ES6提供了新的数据结构Set,Set对象不是数组, 可以用来保存对象或者基本类型, 所有保存的值都是唯一的, chrome浏览器>38和FF>13,以及nodeJS ...

  2. python 生成图形验证码

    文章链接:https://mp.weixin.qq.com/s/LYUBRNallHcjnhJb1R3ZBg 日常在网站使用过程中经常遇到图形验证,今天准备自己做个图形验证码,这算是个简单的功能,也适 ...

  3. C# 利用SharpZipLib生成压缩包

    本文通过一个简单的小例子简述SharpZipLib压缩文件的常规用法,仅供学习分享使用,如有不足之处,还请指正. 什么是SharpZipLib ? SharpZipLib是一个C#的类库,主要用来解压 ...

  4. 如何利用Vagrant快速搭建相同配置的开发环境?

    作为一名程序猿,我们常常会遇到需要搭建开发环境的问题,特别是在新入职的时候,sublime, node, apache, mysql, php等等以及各种框架的安装.如果入职的是大公司有可能这些必要的 ...

  5. sql取指定时间段内的所有月份

    declare @begin datetime,@end datetime set @begin='2017-01-01' set @end='2019-03-04' declare @months ...

  6. 利用ZYNQ SOC快速打开算法验证通路(3)——PS端DMA缓存数据到PS端DDR

    上篇该系列博文中讲述W5500接收到上位机传输的数据,此后需要将数据缓存起来.当数据量较大或者其他数据带宽较高的情况下,片上缓存(OCM)已无法满足需求,这时需要将大量数据保存在外挂的DDR SDRA ...

  7. python文章装饰器理解12步

    1. 函数 在python中,函数通过def关键字.函数名和可选的参数列表定义.通过return关键字返回值.我们举例来说明如何定义和调用一个简单的函数: def foo(): return 1 fo ...

  8. SQLServer之数据类型解析

    数字 int.bigint.smallint 和 tinyint 使用整数数据的精确数字数据类型. 数据类型 范围 存储 tinyint 0 到 255. 1 字节 smallint -2^15 (- ...

  9. Netstat 常用命令--备忘录

    Netstat 用于显示与IP .TCP .UDP 和ICMP 协议相关的统计数据,一般用于检验本机各端口的网络连接情况. 常用参数 -a (all)显示所有选项,默认不显示LISTEN相关-t (t ...

  10. day 9~11 函数

    今日内容 '''函数四个组成部分函数名:保存的是函数的地址,是调用函数的依据函数体:就是执行特定功能的代码块函数返回值:代码块执行的结果反馈函数参数:完成功能需要的条件信息​1.函数的概念2.函数的定 ...