全网最适合入门的面向对象编程教程:58 Python 字符串与序列化-序列化 Web 对象的定义与实现

摘要:

如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML\YAML\JSON格式这种序列化Web对象。这种序列化Web对象容易与其他程序设计语言交互,可读性强,容易被传递给其它系统或客户端。

原文链接:

FreakStudio的博客

往期推荐:

学嵌入式的你,还不会面向对象??!

全网最适合入门的面向对象编程教程:00 面向对象设计方法导论

全网最适合入门的面向对象编程教程:01 面向对象编程的基本概念

全网最适合入门的面向对象编程教程:02 类和对象的 Python 实现-使用 Python 创建类

全网最适合入门的面向对象编程教程:03 类和对象的 Python 实现-为自定义类添加属性

全网最适合入门的面向对象编程教程:04 类和对象的Python实现-为自定义类添加方法

全网最适合入门的面向对象编程教程:05 类和对象的Python实现-PyCharm代码标签

全网最适合入门的面向对象编程教程:06 类和对象的Python实现-自定义类的数据封装

全网最适合入门的面向对象编程教程:07 类和对象的Python实现-类型注解

全网最适合入门的面向对象编程教程:08 类和对象的Python实现-@property装饰器

全网最适合入门的面向对象编程教程:09 类和对象的Python实现-类之间的关系

全网最适合入门的面向对象编程教程:10 类和对象的Python实现-类的继承和里氏替换原则

全网最适合入门的面向对象编程教程:11 类和对象的Python实现-子类调用父类方法

全网最适合入门的面向对象编程教程:12 类和对象的Python实现-Python使用logging模块输出程序运行日志

全网最适合入门的面向对象编程教程:13 类和对象的Python实现-可视化阅读代码神器Sourcetrail的安装使用

全网最适合入门的面向对象编程教程:全网最适合入门的面向对象编程教程:14 类和对象的Python实现-类的静态方法和类方法

全网最适合入门的面向对象编程教程:15 类和对象的 Python 实现-__slots__魔法方法

全网最适合入门的面向对象编程教程:16 类和对象的Python实现-多态、方法重写与开闭原则

全网最适合入门的面向对象编程教程:17 类和对象的Python实现-鸭子类型与“file-like object“

全网最适合入门的面向对象编程教程:18 类和对象的Python实现-多重继承与PyQtGraph串口数据绘制曲线图

全网最适合入门的面向对象编程教程:19 类和对象的 Python 实现-使用 PyCharm 自动生成文件注释和函数注释

全网最适合入门的面向对象编程教程:20 类和对象的Python实现-组合关系的实现与CSV文件保存

全网最适合入门的面向对象编程教程:21 类和对象的Python实现-多文件的组织:模块module和包package

全网最适合入门的面向对象编程教程:22 类和对象的Python实现-异常和语法错误

全网最适合入门的面向对象编程教程:23 类和对象的Python实现-抛出异常

全网最适合入门的面向对象编程教程:24 类和对象的Python实现-异常的捕获与处理

全网最适合入门的面向对象编程教程:25 类和对象的Python实现-Python判断输入数据类型

全网最适合入门的面向对象编程教程:26 类和对象的Python实现-上下文管理器和with语句

全网最适合入门的面向对象编程教程:27 类和对象的Python实现-Python中异常层级与自定义异常类的实现

全网最适合入门的面向对象编程教程:28 类和对象的Python实现-Python编程原则、哲学和规范大汇总

全网最适合入门的面向对象编程教程:29 类和对象的Python实现-断言与防御性编程和help函数的使用

全网最适合入门的面向对象编程教程:30 Python的内置数据类型-object根类

全网最适合入门的面向对象编程教程:31 Python的内置数据类型-对象Object和类型Type

全网最适合入门的面向对象编程教程:32 Python的内置数据类型-类Class和实例Instance

全网最适合入门的面向对象编程教程:33 Python的内置数据类型-对象Object和类型Type的关系

全网最适合入门的面向对象编程教程:34 Python的内置数据类型-Python常用复合数据类型:元组和命名元组

全网最适合入门的面向对象编程教程:35 Python的内置数据类型-文档字符串和__doc__属性

全网最适合入门的面向对象编程教程:36 Python的内置数据类型-字典

全网最适合入门的面向对象编程教程:37 Python常用复合数据类型-列表和列表推导式

全网最适合入门的面向对象编程教程:38 Python常用复合数据类型-使用列表实现堆栈、队列和双端队列

全网最适合入门的面向对象编程教程:39 Python常用复合数据类型-集合

全网最适合入门的面向对象编程教程:40 Python常用复合数据类型-枚举和enum模块的使用

全网最适合入门的面向对象编程教程:41 Python常用复合数据类型-队列(FIFO、LIFO、优先级队列、双端队列和环形队列)

全网最适合入门的面向对象编程教程:42 Python常用复合数据类型-collections容器数据类型

全网最适合入门的面向对象编程教程:43 Python常用复合数据类型-扩展内置数据类型

全网最适合入门的面向对象编程教程:44 Python内置函数与魔法方法-重写内置类型的魔法方法

全网最适合入门的面向对象编程教程:45 Python实现常见数据结构-链表、树、哈希表、图和堆

全网最适合入门的面向对象编程教程:46 Python函数方法与接口-函数与事件驱动框架

全网最适合入门的面向对象编程教程:47 Python函数方法与接口-回调函数Callback

全网最适合入门的面向对象编程教程:48 Python函数方法与接口-位置参数、默认参数、可变参数和关键字参数

全网最适合入门的面向对象编程教程:49 Python函数方法与接口-函数与方法的区别和lamda匿名函数

全网最适合入门的面向对象编程教程:50 Python函数方法与接口-接口和抽象基类

全网最适合入门的面向对象编程教程:51 Python函数方法与接口-使用Zope实现接口

全网最适合入门的面向对象编程教程:52 Python函数方法与接口-Protocol协议与接口

全网最适合入门的面向对象编程教程:53 Python字符串与序列化-字符串与字符编码

全网最适合入门的面向对象编程教程:54 Python字符串与序列化-字符串格式化与format方法

全网最适合入门的面向对象编程教程:55 Python字符串与序列化-字节序列类型和可变字节字符串

全网最适合入门的面向对象编程教程:56 Python字符串与序列化-正则表达式和re模块应用

全网最适合入门的面向对象编程教程:57 Python字符串与序列化-序列化与反序列化

更多精彩内容可看:

给你的 Python 加加速:一文速通 Python 并行计算

一文搞懂 CM3 单片机调试原理

肝了半个月,嵌入式技术栈大汇总出炉

电子计算机类比赛的“武林秘籍”

一个MicroPython的开源项目集锦:awesome-micropython,包含各个方面的Micropython工具库

Avnet ZUBoard 1CG开发板—深度学习新选择

SenseCraft 部署模型到Grove Vision AI V2图像处理模块

文档和代码获取:

可访问如下链接进行对文档下载:

https://github.com/leezisheng/Doc

本文档主要介绍如何使用 Python 进行面向对象编程,需要读者对 Python 语法和单片机开发具有基本了解。相比其他讲解 Python 面向对象编程的博客或书籍而言,本文档更加详细、侧重于嵌入式上位机应用,以上位机和下位机的常见串口数据收发、数据处理、动态图绘制等为应用实例,同时使用 Sourcetrail 代码软件对代码进行可视化阅读便于读者理解。

相关示例代码获取链接如下:https://github.com/leezisheng/Python-OOP-Demo

正文

序列化 Web 对象

如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如 XML\YAML\JSON 格式这种序列化 Web 对象。这种序列化 Web 对象容易与其他程序设计语言交互,可读性强,容易被传递给其它系统或客户端。

在 Python 最常用的序列化 Web 对象就是环境配置的 yaml 文件,anaconda 可以管理不同的环境配置,当我们想将自己的环境配置分享给其他人时,就可以生成 yaml 文件,这样别人可以快速导入 yaml 文件构建和我们一样的环境来运行代码。

我们可以在命令行中使用如下指令生成 yaml 文件:

conda env export > environment.yml

使用 JSON 实现序列化 Web 对象

JavaScript Object Notation(JSON)是一种人类可读的格式,用于存储基础数据类型。JSON 是一种标准格式,可以被各式各样的客户端系统解析。因此,JSON 非常适合用于在完全不同的系统之间进行数据传输。而且,JSON 不支持任何可执行代码,只有数据可以被序列化;因此,更难向其中植入恶意代码。JSON 格式因其易于被 JavaScript 引擎解析的特性,常被用于 Web 服务器与具备 JavaScript 功能的浏览器间的数据传输。若 Web 应用的服务器端采用 Python 编写,为确保数据的兼容性与通用性,需将内部数据转换为 JSON 格式。

我们可以使用 Python 中的 json 模块生成 JSON 文件,该模块与 pickle 类似,也提供了 dumps()、dump()、loads()、load()四个函数,但输出结果是 JSON 格式的。此外,json 函数作用于 str 对象,而不是 bytes。因此,当输出或载入时,我们需要创建文本模式的文件而不是二进制模式。JSON 只能序列化基本类型,如整数、浮点数和字符串,以及简单的容器,如字典和列表。这些都直接映射到 JSON 形式,不过** JSON 不能表示类、方法或函数。不能用这种格式来传输完整的对象。因为接收者通常不是 Python 对象,接收者不能与 Python 以同样的方式来理解类或方法。**

import json

_# 人员信息列表_
humaninfodic={
'age' : 18,
'name' : True,
'gender': 10,
'email' : 11.1,
} _# 序列化到文件中_
with open('test.json', 'w') as fp:
json.dump(humaninfodic, fp, indent=4) _# 反序列化文件中的内容_
with open('test.json', 'r') as fp:
dic = json.load(fp)
print(dic)

运行结果如下:

这里,需要注意的是,Python 中字典的非字符的值 Key 被转换成 JSON 字符串时都会被转换为小写字符串,例如 True 会被映射为 true,False 被映射为 false,而 None 会被映射为 null;同时 Python 中的元组在序列化时会被转换为 array 类型,但是反序列化时,array 类型会被转化为 Python 中的列表类型。

JSON 和 Python 内置的数据类型对应如下:

JSON 类型 Python 类型
{} dict
[] list
"string" str
1234.56 int 或 float
true/false True/False
null None

如果想要序列化的对象只有数据,我们可以直接序列化对象的__dict__属性。或者我们也可以针对特定的对象,通过自定义代码来创建或解析 JSON 序列化字典。

在 json 模块中,对象的存储和载入功能均设有一个可选参数,用以执行特定的自定义操作。具体来说,dumpdumps方法接受一个名为cls(即“class”的简写,因其为 Python 的保留关键字)的关键字参数。当传递此参数时,它必须是 JSONEncoder 的一个子类,并且要求重写了 default 方法。这个方法的设计初衷是接收任意类型的对象作为参数,然后将其转换为 json 能够处理的字典类型。如果在处理过程中遇到不知道如何处理的对象类型,可以通过调用 super() 方法,使得该对象能够按照正常的方式进行序列化处理,即按照基本类型进行序列化。

同样地,loadloads方法也接受一个名为cls的参数,它是JSONDecoder的一个子类。通常情况下,通过object_hook关键字传递一个函数便足够了。这个函数的任务是接收一个字典作为参数,并返回一个对象。如果在处理过程中遇到不知道如何处理的字典,可以选择不进行任何修改,直接将其返回。这种设计使得用户在进行 json 数据的解析时,能够更加灵活和方便地处理各种复杂的数据类型。

import json

_# 定义联系人类_
class Contact:
def __init__(self, first, last):
_# 属性1,first name是名字_
self.first = first
_# 属性2,last name是姓氏_
self.last = last
@property
def full_name(self):
return("{} {}".format(self.first, self.last)) _# 自定义序列化编码器类_
class ContactEncoder(json.JSONEncoder):
_# default 方法检查了我们想要序列化的对象类型_
def default(self, obj):
_# 如果是联系人类,我们手动将其转换为字典_
if isinstance(obj, Contact):
return {
_# 传递了一个额外的属性来说明这是一个联系人对象_
_# 因为没有其他办法可以在载入之后知道它的类型_
'is_contact': True,
'first': obj.first,
'last': obj.last,
'full': obj.full_name}
_# 否则,让其父类来处理序列化(假设它是基本类型,json 知道如何处理)_
return super().default(obj) _# 定义一个JSON文件解码器函数_
def decode_contact(dic):
_# 写一个函数接受字典为参数_
_# 检查是否包含 is_contact 变量来决定是否将其转换为联系人_
if dic.get('is_contact'):
return Contact(dic['first'], dic['last'])
else:
return dic if __name__ == '__main__':
c = Contact("John", "Smith")
data = json.dumps(c, cls=ContactEncoder)
print(data)
c = json.loads(data, object_hook=decode_contact)
print(c.full_name)

运行结果如下:

使用 XML 实现序列化 Web 对象

在当今的软件开发领域,XML 作为一种灵活且强大的标记语言,已经广泛应用于数据存储、配置管理、网络传输等多个场景。它的可扩展性和自描述性让它成为了不同系统和平台之间数据交换的理想格式。

XML 指可扩展标记语言(eXtensible Markup Language),是一套定义语义标记的规则,这些标记将文档分成许多部件并对这些部件加以标识,它被设计用来传输和存储数据,不用于表现和展示数据。它也是元标记语言,即定义了用于定义其他与特定领域有关的、语义的、结构化的标记语言的句法语言。

如下我们列举了一个 xml 文件的例子:

<?xml version="1.0" encoding="utf-8"?>
<catalog>
<maxid>4</maxid>
<login username="pytest" passwd='123456'>
<caption>Python</caption>
<item id="4">
<caption>测试</caption>
</item>
</login>
<item id="2">
<caption>Zope</caption>
</item>
</catalog>

以上 XML 格式的文件中,包含了一个名为"catalog"的根元素。根元素下有一个名为"maxid"的子元素,其值为"4"。接着是一个名为"login"的子元素,它包含两个子元素:一个名为"caption"的子元素,其值为"Python";另一个名为"item"的子元素,其 id 属性值为"4",包含一个名为"caption"的子元素,其值为"测试"。最后还有一个名为"item"的子元素,其 id 属性值为"2",包含一个名为"caption"的子元素,其值为"Zope"。

其中书名号圈住的部分“”为标签,标签必须成对出现,有开始标签就需要有结束标签,例如”“为开始标签,“”为结束标签。

一个基本的 XML 文档结构包括以下部分:

结构部分 作用
声明部分 位于文档的最开始,声明 XML 的版本和编码方式。例如:。
根元素 每个 XML 文档都有一个根元素,它包含了所有其他元素。
子元素 根元素内部可以包含多个子元素,子元素可以嵌套并形成树状结构。
属性 元素可以有属性,属性提供了关于元素的额外信息。
文本内容 元素可以包含文本内容。

Python 作为一门简洁而强大的编程语言,提供了丰富的库来处理 XML 数据,使得从解析到修改再到创建 XML 文档变得既简单又高效。Python 有三种方法解析 XML、SAX、DOM,以及 ElementTree。

其中,xml.etree.ElementTree(简称 ET)提供了一个轻量级的 Pythonic 方式来处理 XML 数据。ET 允许用户轻松地读取、修改和创建 XML 文件。由于是标准库的一部分,因此不需要额外安装即可使用,这使得它成为处理 XML 数据的一个便捷选择。

对于 ElementTree 库来说,常见使用操作包括解析 XML 文档,获取根元素、遍历子元素、读取元素的标签、文本和属性,以及如何根据需要获取或删除特定元素,以及保存修改后的 XML 文档。

这里,对于 XML 文件仅作为了解使用,并不展开进行讲解。

使用 YAML 实现序列化 Web 对象

XML 文件虽然功能强大,但由于其标记语言的特性,通常不太易于阅读。相反,XML 在需要对验证、架构和名称空间进行精细控制的复杂项目中表现出色。与 XML 相比,YAML 则专注于数据格式化,以可读代码的形式呈现,其内联风格与 JSON 颇为相似。YAML 旨在提供更为直观和易读的数据表示方式,以满足不同场景下的需求。

YAML,作为一种高度人性化的数据序列化语言,能够与当前主流的编程语言无缝集成。其名称“YAML”来源于“YAML Ain't a Markup Language”(YAML 不是一种标记语言)的递归缩写,这一命名既体现了其独特性,又突显了其与众不同的设计理念。

YAML 的语法结构与其他高级语言相似,能够轻松表达清单、散列表以及标量等多种数据形态。它巧妙地利用空白符号进行缩进,并大量依赖外观特征来展示数据结构的层次关系。这种设计使得 YAML 特别适合用于编辑数据结构、编写各种配置文件、打印调试信息以及呈现文件大纲等场景。

此外,YAML 配置文件通常以“.yml”作为文件后缀,这一命名约定有助于用户快速识别和管理 YAML 文件。

它的基本语法规则如下:

(1)大小写敏感;

(2)使用缩进表示层级关系;

(3)缩进时不允许使用 Tab 键,只允许使用空格。

(4)缩进的空格数目不重要,只要相同层级的元素左侧对齐即可

YAML 支持的数据结构有三种:

(1)对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary);

(2)数组:一组按次序排列的值,又称为序列(sequence) / 列表(list);

(3)纯量(scalars):单个的、不可再分的值。

在 Python 中,有多个库可用于解析和生成 YAML 数据,其中最常用的是 PyYAML。

这里,我们以下列名为 config.yaml 的 YAML 配置文件为例,简单讲解一下 YAML 文件语法:

_# 配置文件示例_

_# 服务器配置_
server:
host: localhost
port: 8080 _# 数据库配置_
database:
type: MySQL
host: 127.0.0.1
port: 3306
username: root
password: password _# 日志记录_
logging:
level: info
file: app.log _# 应用配置_
app:
debug: true
log_level: info

这里,该文件使用井号(#)表示注释,使用缩进表示层级关系,并且使用冒号(:)分隔键和值。

这个 YAML 文件包含以下几个部分:

(1)服务器配置:包括主机名和端口号;

(2)数据库配置:包括数据库类型、主机名、端口号、用户名和密码;

(3)日志记录:包括日志级别和日志文件路径;

(4)应用配置:包括是否开启调试模式和日志级别。

XML 和 YAML 文件都有一些复杂的特征,如果被恶意利用,就可以允许在主机上执行任意命令。这与 JSON 文件不同,JSON 不支持任何可执行代码,只有数据可以被序列化。

全网最适合入门的面向对象编程教程:58 Python字符串与序列化-序列化Web对象的定义与实现的更多相关文章

  1. [Java入门笔记] 面向对象编程基础(二):方法详解

    什么是方法? 简介 在上一篇的blog中,我们知道了方法是类中的一个组成部分,是类或对象的行为特征的抽象. 无论是从语法和功能上来看,方法都有点类似与函数.但是,方法与传统的函数还是有着不同之处: 在 ...

  2. 最适合入门的Laravel中级教程(一)

    Laravel 是一个全栈框架: 我们使用 Laravel 开发业务常见有 3 个方向: 前端页面和后端逻辑混合的应用 主要是面向对 SEO 有需求的项目: 比如说新闻资讯博客文章等: 一般在控制器中 ...

  3. JavaScript基础入门12 - 面向对象编程

    目录 JavaScript 面向对象编程 前言 构造函数创建对象 instanceof constructor 返回值 原型对象 关于对象的属性查找 in hasOwnProperty() JS当中实 ...

  4. Python入门之面向对象编程(一)面向对象概念及优点

    概念 谈到面向对象,很多程序员会抛出三个词:封装.继承和多态:或者说抽象.一切都是对象之类的话,然而这会让初学者更加疑惑.下面我想通过一个小例子来说明一下 面向对象一般是和面向过程做对比的,下面是一个 ...

  5. [Java入门笔记] 面向对象编程基础(一):类和对象

    什么是面向对象编程? 我们先来看看几个概念: 面向过程程序设计 面向过程,是根据事情发展的步骤,按进行的顺序过程划分,面向过程其实是最为实际的一种思考方式,可以说面向过程是一种基础的方法,它考虑的是实 ...

  6. 最适合入门的Laravel中级教程(二)用户认证

    之前的初级教程主要是学习简单的增删改查: 接着的中级教程的目标是在初级教程的基础上能写出更复杂更健壮的程序: 我们先来学习 laravel 的用户认证功能: 在现代网站中基本都有用户系统: 而我们每开 ...

  7. Python - 面向对象编程 - 什么是 Python 类、类对象、实例对象

    什么是对象和类 https://www.cnblogs.com/poloyy/p/15178423.html Python 类 类定义语法 最简单的类定义看起来像这样 class ClassName: ...

  8. 06-03 Java 面向对象思想概述、开发设计特征,类和对象的定义使用,对象内存图

    面向对象思想概述.开发设计特征 1:面向对象思想 面向对象是基于面向过程的编程思想. 面向过程:强调的是每一个功能的步骤 面向对象:强调的是对象,然后由对象去调用功能 2:面向对象的思想特点 A:是一 ...

  9. Python入门之面向对象编程(四)Python描述器详解

    本文分为如下部分 引言——用@property批量使用的例子来引出描述器的功能 描述器的基本理论及简单实例 描述器的调用机制 描述器的细节 实例方法.静态方法和类方法的描述器原理 property装饰 ...

  10. [Java入门笔记] 面向对象编程基础(三):成员变量和局部变量

    在类中,变量根据定义的位置不同,可以分为成员变量和局部变量.

随机推荐

  1. JavaScript设计模式样例十三 —— 模版方法模式

    模板方法模式(Template Method Pattern) 定义:一个抽象类公开定义了执行它的方法的方式/模板.它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行.目的:一些方法通用 ...

  2. Html 使用scss爆红

      使用     <style  lang="less" scoped> </style>   即可      

  3. Spring:基于注解管理bean

    标记与扫描 注解 和 XML 配置文件一样,注解本身并不能执行,注解本身仅仅只是做一个标记,具体的功能是框架检测 到注解标记的位置,然后针对这个位置按照注解标记的功能来执行具体操作. 本质上:所有一切 ...

  4. 【YashanDB数据库】YAS-02024 lock wait timeout, wait time 0 milliseconds

    [标题]错误码处理 [问题分类]锁等待超时 [关键字]YAS-02024 [问题描述]执行语句时候,因锁等待超时执行语句失败 [问题原因分析]数据库默认锁等待时间为0秒,如果执行语句存在锁等待过长会执 ...

  5. 【YashanDB知识库】账号被锁,如何分析具体原因

    问题现象 客户刚开始使用YashanDB的时候,经常收到客户反馈账号被锁,但是不知道哪里触发了. 问题的风险及影响 客户环境为测试环境,影响测试业务的开展. 问题影响的版本 YashanDB版本:23 ...

  6. axis2添加拦截器

    项目背景: 2002年的某保险老项目,项目是部署了多个服务器,每个服务器有2到多个服务(每个服务的日志对应一个日志文件),外部对接是通过F5分发到随机服务器上来进行访问,正式出现问题或者看一些问题就需 ...

  7. ASP.NET Core – 网站发布要做的事儿 Publish, Minification, Compression, Cache, HSTS, URL Rewrite Https & www, Close IIS Feature

    前言 要发布网站需要做一些优化, 比如 cache, compression, minification 等等. 以前有写过相关的文章: Asp.net core 学习笔记 ( IIS, static ...

  8. GPT最佳实践:五分钟打造你自己的GPT

    前几天OpenAI的My GPTs栏目还是灰色的,就在今天已经开放使用了.有幸第一时间体验了一把生成自己的GPT,效果着实惊艳!!!我打造的GPT模型我会放到文章末尾,大家感兴趣也可以自己体验一下. ...

  9. Driud——数据库连接池的使用

    Druid数据库连接池的使用 1. 导入 jar 包 jar包下载:Central Repository: com/alibaba/druid/1.1.12 (maven.org) 导入项目中:(复制 ...

  10. [OI] pb_ds

    using namespace __gnu_pbds; Luogu Post#39 1.堆 1.1 基本信息 头文件 #include <ext/pb_ds/priority_queue.hpp ...