Python之路 - 序列化
介绍 🍀
先说个例子 , 当我们将一个字典或者列表再或者变量存入磁盘中 , 而存入磁盘后原本数据类型就得不到保持了 . 这个时候我们就得用序列化和反序列化了
序列化是将对象进行存储时保持当时对象的状态 , 实现其生命周期的延长
反序列化则是将存储的对象读取出来并转成原本的数据类型
序列化的目的
- 以某种存储形式使自定义对象持久化
- 将对象从一个地方传递到另一个地方
- 使程序更具维护性
先说个例子 , 当我们将一个字典或者列表再或者变量存入磁盘中 , 而存入磁盘后原本数据类型就得不到保持了 . 这个时候我们就得用序列化和反序列化了
序列化是将对象进行存储时保持当时对象的状态 , 实现其生命周期的延长
反序列化则是将存储的对象读取出来并转成原本的数据类型
序列化的目的
编程范式
编程是程序员用 特定的语法 + 数据结构 + 算法组成的代码来告诉计算机如何执行任务的过程 , 而实现一个任务的方式有很多种不同的方式 , 对这些不同的编程方式的特点进行归纳总结得出来的编程方式类别,即为编程范式
面向过程编程就是程序从上到下一步步执行 , 基本设计思路就是程序一开始是要着手解决一个大的问题 , 然后把一个大问题分解成很多个小问题或子过程 , 这些子过程再执行的过程再继续分解直到小问题足够简单到可以在一个小步骤范围内解决
在Python中 , 我们通过把大段代码拆成函数 , 通过一层一层的函数调用 , 就可以把复杂任务分解成简单的任务 , 这种分解可以称之为面向过程的程序设计 . 函数就是面向过程的程序设计的基本单元
函数式编程就是一种抽象程度很高的编程范式 , 纯粹的函数式编程语言编写的函数没有变量 , 函数式编程的一个特点就是 , 允许把函数本身作为参数传入另一个函数 , 还允许返回一个函数 , Python对函数式编程提供部分支持 . 由于Python允许使用变量 , 因此 , Python不是纯函数式编程语言
面向对象编程是利用”类”和”对象”来创建各种模型来实现对真实世界的描述 , 使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单 , 并且可以大大提高程序开发效率 , 另外 , 基于面向对象的程序可以使它人更加容易理解你的代码逻辑 , 从而使团队开发变得更从容
tarfile和zipfile,shutil都是文件压缩,打包,解压的模块.其中shuttile还支持文件的拷贝,复制等功能
1 | import zipfile |
抽象
抽象是从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征
比如 🍎 , 🍌 , 🍇 , 等 , 它们共同的特性就是水果 , 我们得出水果这个概念的过程就是一个抽象的过程 , 抽象能使复杂度降低 , 好让人们能够以宏观的角度来了解许多特定的事态
有抽象就会有具体 , 我们会用抽象的对象来表示一类事物 , 而用具体的对象表示某个事物 , 比如苹果 , 香蕉 , 葡萄都是具体的对象 , 水果则是抽象的对象
继承
继承是基于抽象的结果
抽象可以让我们来以宏观的角度了解一类事物事物 , 并且这类事物都拥有该抽象中所有的特征 , 相当于继承了该抽象中的特征 , 这样我们就可以只将这类事物不同的特征放到具体中 , 而不需要再次关心共同特征 , 所以先有抽象后才能有继承
介绍抽象的概念时利用了水果来进行说明 , 为了更好的理解 , 继承就用动物为例子
封装就是把客观事物封装成抽象的类 , 并且类可以把自己的数据和方法只让可信的类或者对象操作 , 对不可信的进行信息隐藏
当我们类中的一些属性或者方法想要对不可信的类或者对象隐藏时 , 我们就可以将这些属性或者方法 , 定义成私有属性或者私有方法
在Python中用双下划线开头的方式将属性隐藏起来 , 即带双下划线就为私有属性或者私有方法
1 | class A: |
上一篇中已经得知 , 继承可以扩展已存在的代码模块(类) , 其目的是为了解决代码重用 问题
多态则是为了实现另一个目的 : 接口重用
多态 (Polymorphism) 按字面的意思就是”多种状态” , 比如动物有多种形态 , 人 , 猫 , 狗 ; 文件也有多种格式 exe , txt , md(MarkDown格式) , 这就是多态
在面向对象语言中 , 接口的多种不同的实现方式即为多态
多态性是允许你将父对象设置成为一个或多个他的子对象相等的技术 , 赋值之后 , 父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作
静态多态性
属性方法就是通过使用装饰器 @property
, 将一个方法变成一个静态属性 , 于是我们就可以通过访问属性 , 来或得一个方法的返回值
1 | from urllib.request import urlopen |
反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力
Python面向对象中的反射是通过字符串的形式来操作对象相关的属性 , 在Python中一切皆对象 , 并且只要是对象就可以使用反射
判断对象中是否具有给定名称的属性
1 | def hasattr(*args, **kwargs): # real signature unknown |
实例1
1 | # 定义一个字符串 |
实例2
1 | import sys |
从一个对象中获取属性名称
在我们写程序时难免会出现错误 , 一种为语法错误 , 即为python解释器的语法检测都通不过的错误 , 这种错误只能我们在程序执行前就处理好 . 另一种为逻辑错误 , 这是我们在程序设计时所出现的错误 , 也就是我们通常所说的bug
在编程过程中为了增加友好性 , 在程序出现bug时一般不会将错误信息显示给用户 , 而是显示一个提示错误的页面
基本语法
在 Python 中 , 我们自定义类都是基于 Object 对象实现的 , 而在 Object 对象中有一些特殊的操作符 (__method__
) 控制着整个对象的行为 , 所以 , 如果我们想对对象的行为进行控制 , 我们就需要自己来实现这些方法 ; 当然很多人称这些方法为 Python 魔法方法 (魔术方法)
下面 , 看看这些方法吧
操作符 | 控制行为 | 调用说明 |
---|---|---|
__new__ |
对象创建 | __init__ 只是用处初始化 , __new__ 调用的结果会交给 __init__ 进一步处理 |
__init__ |
对象初始化 | 构造函数 , 进行属性设置 |
__del__ |
对象删除 | 析构函数 , 进行对象的销毁 |
__repr__ |
对象显示 , 针对对象 | 终端显示 , 返回值必须为字符串 , 实例见表下方 |
__str__ |
对象显示 , 针对 print |
print 显示结果 , 返回值必须为字符串 , 如果未实现该方法 , print 将使用 __repr__ |
__bytes__ |
字节对象转换 | 返回值必须为一个bytes对象 , bytes(obj) |
__format__ |
格式化字符串 | 返回值必须为字符串对象 , format(obj) |
__lt__ |
< 运算 |
x < y , 返回布尔值 , 下同 |
__le__ |
<= 运算 |
x <= y |
__eq__ |
= 运算 |
x == y |
__ne__ |
!= 运算 |
x != y |
__gt__ |
> 运算 |
x > y |
__ge__ |
>= 运算 |
x >= y |
__hash__ |
可哈希 | 返回一个哈希对象 , hash(obj) , 注意 : 定义该方法同时应该定义 __eq__ |
__bool__ |
真假测试 | 返回布尔值 |
__call__ |
对象调用 | 在对象被调用时执行 |
__len__ |
len() |
使用 len(obj) 时被调用 , 为防止值测试抛出 OverflowError , 必须定义 __bool__() |
__repr__
与 __str__
对比实例 :