序列化和反序列化
按照某种规则,把内存的数据保存到文件中,文件是一个字节序列,所以把数据转换成字节序列保存在文件中,这个过程叫序列化,相反,把文件中的字节序列恢复到内存称为反序列化。
1 import pickle 2 a = 123 3 b = '123' 4 c = [1, 2, 3] 5 d = {'a': 1, 'b': '2', 3: (3,)} 6 with open('test', 'wb') as f: # 序列化 7 pickle.dump(a, f) 8 pickle.dump(b, f) 9 pickle.dump(c, f) 10 pickle.dump(d, f) 11 with open('test', 'rb') as f: # 反序列化 12 for i in range(4): 13 x = pickle.load(f) 14 print(type(x), x) 15 # <class 'int'> 123 16 # <class 'str'> 123 17 # <class 'list'> [1, 2, 3] 18 # <class 'dict'> {'a': 1, 'b': '2', 3: (3,)}
1 import pickle 2 3 4 class AAA: 5 tttt = 'ABC' 6 7 def __init__(self): 8 self.aaaa = 'abcd' 9 10 11 def show(self): 12 print('ABCD') 13 14 15 a = AAA() 16 a.show() # ABCD 17 print(a.tttt, a.aaaa) # ABC abcd 18 with open('test', 'wb') as f: 19 pickle.dump(a, f)
在另一个终端
1 import pickle 2 class AAA: 3 pass 4 with open('D:/python/test', 'rb') as f: 5 b = pickle.load(f) 6 print(b.aaaa) # abcd
b.show(),b.tttt均报错,所以只保存了__init__里的内容
1 import pickle 2 3 4 class AAA: 5 tttt = 'ABC' 6 7 def __init__(self): 8 self.aaaa = 'abcd' 9 10 11 def show(self): 12 print('ABCD') 13 14 15 a = AAA() 16 a.show() # ABCD 17 print(a.tttt, a.aaaa) # ABC abcd 18 p = pickle.dumps(a) # 序列化 19 with open('text', 'wb') as f: 20 f.write(p)
在另一个终端
1 import pickle 2 with open('D:/python/test', 'rb') as f: 3 b = f.read() 4 c = pickle.loads(b) # 反序列化5 print(c.aaaa) # abcd
这次把类名也保存了下来
pickle适合Python程序之间使用。跨平台,跨语言,跨写一下pickle不适用,需使用公共协议,如XML、Json、Protocol Buffer等
Json
Json(JavaScript Object Notation)是一种轻量级的数据交换格式,支持字符串,必须用双引号包起来,数值(正负整数,浮点数),对象(字典),数组(列表),true(True),false(False),null(None)
json模块
1 import json 2 obj = {'name': 'Tom', 'age': 18, 'class': ['Python', 'Linux']} 3 f = json.dumps(obj) # json转码 4 g = json.loads(f) # json解码 5 print(type(obj), obj) # <class 'dict'> {'name': 'Tom', 'age': 18, 'class': ['Python', 'Linux']} 6 print(type(f), f) # <class 'str'> {"name": "Tom", "age": 18, "class": ["Python", "Linux"]} 7 print(type(g), g) # <class 'dict'> {'name': 'Tom', 'age': 18, 'class': ['Python', 'Linux']} 8 with open('test', 'w') as f: 9 json.dump(obj, f) # json转码 10 with open('test', 'r') as f: 11 h = json.load(f) # json解码 12 print(type(h), h) # <class 'dict'> {'name': 'Tom', 'age': 18, 'class': ['Python', 'Linux']}
MessagePack
MessagePack是一个基于二进制的高效的对象序列类库,可用于跨语言通信,它像Json那样但比Json高效
msgpack模块
1 import msgpack 2 obj = {'name': 'Tom', 'age': 18, 'class': ['Python', 'Linux']} 3 f = msgpack.dumps(obj) # MessagePack转码 4 g = msgpack.loads(f) # MessagePack解码 5 print(type(obj), obj) # <class 'dict'> {'name': 'Tom', 'age': 18, 'class': ['Python', 'Linux']} 6 print(type(f), f) # <class 'bytes'> b'x83xa4namexa3Tomxa3agex12xa5classx92xa6Pythonxa5Linux' 7 print(type(g), g) # <class 'dict'> {'name': 'Tom', 'age': 18, 'class': ['Python', 'Linux']} 8 with open('test', 'wb') as f: 9 msgpack.dump(obj, f) # MessagePack转码 10 with open('test', 'rb') as f: 11 h = msgpack.load(f) # MessagePack解码 12 print(type(h), h) # <class 'dict'> {'name': 'Tom', 'age': 18, 'class': ['Python', 'Linux']}
面向对象
语言分类
面向机器(汇编语言):抽象成机器指令,机器容易理解
面向过程(C语言):按步骤,一步步进行
面向对象(C++,Java,Python):随着计算机需要解决的问题规模扩大,面向过程不太适合了,而开发出的高级汇编语言,将万事万物抽象为各种对象
类class
类是抽象的概念,是万事万物的抽象,是一类事物共同特征的集合
对象instance,object
对象是类的具象,是一个实体,对于我们每个人这个个体,都是抽象概念人类的不同的实体
属性
对对象状态的抽象,用数据结构来描述
操作
对对象状态的抽象,用操作名和实现操作的方法来描述
面向对象的3要素
封装:将数据和操作组装在一起,对外只暴露部分接口。
继承:多复用,不用重复写代码,多继承少修改,使用继承来改变和体现个性
多态:面向对象编程最灵活的地方,动态绑定
封装
定义类就是封装,将类属性和操作组织在里面
1 class ClassName: # 命名通常使用大驼峰的命名方式 2 """a class""" 3 a = 'abc' # 定义类属性 4 5 def show(self): # 定义类方法 6 return self.__class__.__name__ 7 8 9 print(ClassName) 10 print(ClassName.__name__) # 类名 11 print(ClassName.__doc__) # 类文档 12 print(ClassName.__dict__) # 类字典 13 print(ClassName.show) # 类属性
类及类属性
类对象:类也是对象,类定义后生成一个对象
类属性:类定义中的变量和类的方法都是类的属性,__name__,__doc__等是类的特殊属性
类变量:属性也是标识符,均为变量
实例化
1 class ClassName: 2 """a class""" 3 a = 'abc' 4 5 def show(self): 6 return self.__class__.__name__ 7 8 9 a = ClassName() # 实例化 10 b = ClassName() # 实例化 11 print(a.show) 12 print(b.show)
__init__方法
类实例化后要初始化,会调用__init__(self)方法,可以不定义,如果没有定义会隐式调用其父类的
1 class Test: 2 def __init__(self): 3 print('init') 4 5 6 print(Test) # 不调用 7 Test() # 调用 8 a = Test() # 调用
初始化可以传入多个参数
1 class Test: 2 def __init__(self, a, b): 3 self.a = a 4 self.b = b 5 6 def show(self): 7 print(self.a, self.b) 8 9 10 c = Test(123, 'abc') 11 print(c.a, c.b) # 123 abc 12 c.show() # 123 abc
注意__init__只能return None
实例对象instance
实例化后获得一个该类的实例,就是实例对象
方法绑定
实例化后,调用方法,实例对象会绑定到方法上,指向当前调用该方法的实例本身
slef
1 class Test: 2 def __init__(self): 3 print('init is {}'.format(id(self))) 4 5 def show(self): 6 print('show is {}'.format(id(self))) 7 8 9 a = Test() 10 print('a is {}'.format(id(a))) 11 a.show() 12 # id相等
类变量和实例变量
1 class Test: 2 a = 3 # 类变量 3 4 def show(self): 5 print(self.a) 6 7 8 a = Test() 9 a.show() # 3 10 b = Test() 11 b.a = 5 # 实例变量 12 b.show() # 5
属性本质
1 class Test: 2 a = 3 # 类变量 3 4 def __init__(self, name): 5 self.name = name 6 7 8 print('类') 9 print(Test.__class__, type(Test), Test.__class__ is type(Test)) # <class 'type'> <class 'type'> True 10 print(Test.__dict__) # 类字典 11 b = Test('b') 12 print('实例') 13 print(b.__class__, type(b), b.__class__ is type(b)) # <class '__main__.Test'> <class '__main__.Test'> True 14 print(b.__class__.__name__, type(b).__name__) # Test Test 15 print(b.__class__.__dict__) # 类字典 16 print(b.__dict__) # {'name': 'b'} 17 # 可以看出实例的__class__就是类
类方法和静态方法
定义的__init__等方法,这些方法本身都是类的属性,第一个参数必须是self,而self必须指向一个对象,也就是实例化后由实例调用这个方法
普通函数
1 class Test: 2 3 def show(): 4 print('普通函数') 5 6 7 a = Test 8 a.show() # 普通函数 9 Test.show() # 普通函数 10 # 能运行,但不建议这样用
类方法
1 class Test: 2 @classmethod 3 def show(cls): 4 print('类方法') 5 6 7 a = Test 8 a.show() # 类方法 9 Test.show() # 类方法
静态方法
1 class Test: 2 @staticmethod 3 def show(): 4 print('静态方法') 5 6 7 a = Test 8 a.show() # 静态方法 9 Test.show() # 静态方法
访问控制
1 class Test: 2 def __init__(self, a): 3 self.a = a 4 5 def show(self, i=10): 6 if 0 < i < 50: 7 self.a += i 8 9 10 b = Test(30) 11 print(b.a) # 30 12 b.show(20) 13 print(b.a) # 50 14 b.show(200) 15 print(b.a) # 50
私有属性
开头使用两个下划线的属性名就是私有属性,不能被直接访问
1 class Test: 2 def __init__(self, a): 3 self.__a = a 4 5 def show(self, i=10): 6 if 0 < i < 50: 7 self.__a += i 8 return self.__a 9 10 11 b = Test(30) 12 print(b.show(20)) # 50 13 print(b.show(30)) # 80 14 print(b.show(50)) # 80 15 print(b.__dict__) # {'_Test__a': 80} 16 print(b._Test__a) # 80,私有属性通常不直接从外部访问,若要访问可以用这钟方式访问
保护成员
开头使用一个下划线的属性名就是保护成员,能被直接访问,通常约定不直接访问
1 class Test: 2 def __init__(self, a): 3 self._a = a 4 5 def show(self, i=10): 6 if 0 < i < 50: 7 self._a += i 8 return self._a 9 10 11 b = Test(30) 12 print(b._a) # 30 13 print(b.show(20)) # 50 14 print(b._a) # 50
补丁
可以使用打补丁的方法修改类
1 # test1.py 2 from test2 import Test 3 from test3 import show 4 5 6 print(Test().show()) # test2 7 Test.show = show # 打补丁 8 print(Test().show()) # test3 9 10 # test2.py 11 class Test: 12 def show(self): 13 return 'test2' 14 15 # test3.py 16 def show(self): 17 return 'test3'
属性装饰器
1 # 使用属性装饰器前 2 class Test: 3 def __init__(self, a): 4 self.__a = a 5 6 def show(self): 7 return self.__a 8 9 def set(self, i): 10 self.__a = i 11 12 13 b = Test(30) 14 print(b.show()) # 30 15 b.set(20) 16 print(b.show()) # 20
1 # 使用属性装饰器后 2 class Test: 3 def __init__(self, a): 4 self.__a = a 5 6 @property 7 def show(self): 8 return self.__a 9 10 @show.setter 11 def show(self, i): 12 self.__a = i 13 14 15 b = Test(30) 16 print(b.show) # 30 17 b.show = 20 18 print(b.show) # 20
对象的销毁
调用__del__方法,编译结束的时候自动调用该方法
1 # 使用属性装饰器后 2 class Test: 3 def __init__(self, a): 4 self.__a = a 5 6 def show(self): 7 return self.__a 8 9 def __del__(self): 10 print('end') 11 12 13 a = Test('HI') 14 print(a.show()) # HI 15 # end
方法重载
Python没有重载,Python语法本身实现了重载
类的继承
基本概念
类的三要素:封装,继承,多态
1 # 没有继承 2 class TestOne: 3 def show(self): 4 print('{} show'.format(self.__class__.__name__)) 5 6 7 class TestTwo: 8 def show(self): 9 print('{} show'.format(self.__class__.__name__)) 10 11 12 test1 = TestOne() 13 test1.show() # TestOne show 14 test2 = TestTwo() 15 test2.show() # TestTwo show
1 # 有继承 2 class TestOne: 3 """1""" 4 def show(self): 5 print('{} show'.format(self.__class__.__name__)) 6 7 8 class TestTwo: 9 """2""" 10 def dict(self): 11 print(self.__class__.__dict__) 12 13 14 class TestThree(TestOne, TestTwo): 15 """3""" 16 pass 17 18 19 test1 = TestOne() 20 test1.show() # TestOne show 21 test2 = TestTwo() 22 test2.dict() # TestTwo的字典 23 test3 = TestThree() 24 test3.show() # TestThree show 25 test3.dict() # TestThree的字典 26 print(TestThree.__mro__) # 显示方法查找顺序,基类的元组 27 print(TestThree.mro()) # 同上 28 print(TestThree.__base__) # 返回基类元组的第一项 29 print(TestThree.__bases__) # 返回基类元组
方法的覆盖重写
1 class TestOne: 2 """1""" 3 def show(self): 4 print('{} show'.format(self.__class__.__name__)) 5 6 7 class TestTwo(TestOne): 8 """2""" 9 def show(self): 10 print('覆盖了') 11 12 13 test1 = TestOne() 14 test1.show() # TestOne show 15 test2 = TestTwo() 16 test2.show() # 覆盖了
单继承
定义类的时候继承项只有一个基类的是为单继承
多继承
一个类继承自多个类就是多继承
多继承的弊端:多个父类有相同的方法名的时候不清楚继承哪个
解决方法:Python使用C3算法解决,在类被创建出来的时候就建立了MRO列表
其它解决方法:装饰器,Mixin
多态
在面向对象中,父类,子类,联系在一起,如果通过一套方法,就可以实现不同表现,就是多态