Python基础及语法(九)

序列化和反序列化

按照某种规则,把内存的数据保存到文件中,文件是一个字节序列,所以把数据转换成字节序列保存在文件中,这个过程叫序列化,相反,把文件中的字节序列恢复到内存称为反序列化。

 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'\x83\xa4name\xa3Tom\xa3age\x12\xa5class\x92\xa6Python\xa5Linux'
 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

多态

在面向对象中,父类,子类,联系在一起,如果通过一套方法,就可以实现不同表现,就是多态

 

posted @ 2020-05-20 16:23  _Biko  阅读(176)  评论(0编辑  收藏  举报