序列化是保存复杂对象的有用技术。

在本文中,我们将向您介绍 Python 中的对象序列化,并解释其重要性。序列化本质上是一种存储数据或对象的方式,是一种保存复杂对象的有用技术。 它是将对象转换为可以存储在内存或文件中的字节流的过程。 然后可以重建或反序列化此文件以检索原始对象,然后在不同的程序甚至不同的环境中重复使用。

下面,我们将向您展示一些如何使用 Python 中最流行的序列化工具的示例。如果您是 Python 新手,并且想要培养处理数据的技能,请查看 此专题 。它将教您使用 Python 处理各种文件格式所需的所有知识。

基础课程

请记住,Python 是一种面向对象的语言;几乎所有事物都被视为对象。这意味着您可以序列化存储在列表、字典甚至类实例中的数据。

让我们开始吧,创建一个用于驾驶汽车的类。本文的重点不是类,因此如果您想了解有关类如何工作的更多详细信息,请查看 本文 。我们还有 一些在此基础上构建的材料 ,并向您展示如何用 Python 编写自定义模块。

Python 中的对象具有属性(如其属性)和方法(它可以做的事情)。我们的汽车类的重要属性是当前燃油水平和效率(每公里消耗多少燃油)。这些在 中定义 __init__() 。汽车还可以具有与之相关的多种操作,例如行驶一定距离。这些是类方法,它们在类中以函数形式编写。

以下等级允许您在给定燃油水平和效率的情况下驾驶汽车行驶一定距离:

class Car:
    def __init__(self, efficiency, fuel_level):
        self.efficiency = efficiency
        self.fuel_level = fuel_level
    
    def drive(self, distance):
        max_distance = self.fuel_level * self.efficiency
        
        if distance > max_distance:
            print('Traveled %s km, out of fuel'%(max_distance))
            self.fuel_level = 0
        else:
            self.fuel_level -= distance / self.efficiency
            print('Arrived safely!')

我们可以创建一个效率为 5 km/L、燃油量为 12 L 的汽车对象,如下所示:

fast_car1 = Car(5, 12)

让我们驾驶它行驶 8 公里,然后检查燃油量:

>>> fast_car1.drive(8)
>>> fast_car1.fuel_level
10.4

到目前为止一切顺利。现在我们想序列化该 fast_car1 对象,以便我们可以稍后返回并使用它,而不必再次实例化它。输入 pickle .

泡菜

Python pickle 模块是一个易于使用的模块,用于在 Python 中序列化(pickling)和反序列化(unpickling)对象。可以序列化大量对象,包括布尔值、整数、浮点数和字符串,以及列表、字典、集合等数据结构。函数和类可以序列化,正如我们将在下面看到的,类的实例也可以序列化。

Python pickle 模块以二进制形式存储数据,因此无法供人类阅读。它有四种方法。我们将在本例中使用 dump() load() ,分别用于保存和加载 pickle 文件。另外两种方法是 dumps() loads() ,用于序列化对象而不将其保存到文件中。

我们将在下面仔细研究前两个。但在此之前,请注意:正如官方 文档 , the Python pickle module is not secure against maliciously constructed data that can execute foreign code 。因此, 切勿对来自不受信任来源的数据进行反序列化 .

安全简报结束后,我们继续看一个 Python 中的 pickling 和 unpickling 的例子:

with open('fast_car_object.pkl', 'wb') as out_file:
    pickle.dump(fast_car1, out_file)

执行此代码会在当前工作目录中生成文件 fast_car_object.pkl 。要解开此文件,只需执行以下操作:

with open('fast_car_object.pkl', 'rb') as in_file:
    fast_car2 = pickle.load(in_file)

')和反序列化(' wb ') rb 时使用的不同模式 fast_car1 fast_car2 是两个不同的对象,在内存中的位置不同;但是,它们具有相同的属性和方法。顺便说一句,如果您不熟悉使用语句 with 保存文件,这里有 一些 关于在 Python 中写入文件的资料。

我们提到过,Python 中的几乎所有东西都是对象。列表是一个对象,它具有属性和方法。例如, list.append() 是一种将任意数据附加到列表的简单方法,并 list.reverse() 反转元素。您应该熟悉的还有很多。现在,尝试使用序列化列表,就像 pickle 我们上面所做的那样。或者更好的是,尝试使用字典。嵌套数据结构保存到 CSV 或文本文件会有点麻烦,但使用模块只需两行 pickle

Python 中的 JSON 序列化

JSON 代表 JavaScript 对象表示法,是一种用于存储数据的轻量级格式。以这种格式存储的数据具有与 Python 字典类似的结构,因此看起来不会太陌生。如果您不熟悉如何使用 JSON 文件,请查看 本课程 。它包含交互式练习并教您所有需要了解的知识。

Python 有一个模块, json 如果您希望以这种格式编码或解码数据,它将非常有用。选择此方法而不是模块的原因 pickle 包括它是 标准化的并且与语言无关 。它也更安全并且易于阅读。

json 模块可用于序列化 Python 中的对象。它实现了我们上面看到的四种基本方法。查看 文档 了解更多信息和更多示例。

让我们从使用 json 模块序列化列表的简单示例开始。在这里,我们使用的 dumps() 方法不将数据保存到文件,而是将其序列化为字符串:

>>> import json
	>>> lst = [1, 2, 3, 'a', 'b', 'c']
	>>> lst_dump = json.dumps(lst)
	>>> lst_dump
	'[1, 2, 3, "a", "b", "c"]'

现在,如果我们尝试以相同的方式序列化我们 fast_car1 上面实例化的对象,我们会遇到一个问题:

>>> car_dump = json.dumps(fast_car1)
TypeError: Object of type Car is not JSON serializable

dump() 方法 dumps() 中实现的 JSON 编码器 只能序列化一些基本对象类型 。这些是字典、列表、字符串、整数、浮点数、布尔值和 None。像 这样的复杂对象 fast_car1 需要通过在 Python 中构建自定义编码器来自定义序列化为 JSON 格式。

编写自定义编码器

前进的道路本质上归结为在字典中表示 json 可以序列化的数据。您可以创建一个自定义编码器类来扩展 JSONEncoder 中的类 json ,然后使用常规 dump() dumps() 方法。

让我们仔细看看一个例子。这里的 Car 类与上面的相同,现在有一个新的类 CarJSONEncoder

from json import JSONEncoder

class Car:
    def __init__(self, efficiency, fuel_level):
        self.efficiency = efficiency
        self.fuel_level = fuel_level

    def drive(self, distance):
        max_distance = self.fuel_level * self.efficiency
        
        if distance > max_distance:
            print('Traveled %s km, out of fuel'%(max_distance))
            self.fuel_level = 0
        else:
            self.fuel_level -= distance / self.efficiency
            print('Arrived safely!')

class CarJSONEncoder(JSONEncoder):
    def default(self, obj):
        return obj.__dict__
Then to JSON serialize our object, we do the following:
>>> fast_car1_json = json.dumps(fast_car1, cls=CarJSONEncoder)
>>> fast_car1_json
'{"efficiency": 5, "fuel_level": 10.4}'

我们的自定义类使用 __dict__ ,这是一个内置属性,将对象的属性存储为键/值对。然后我们 cls 在方法中使用关键字参数 dumps() 。输出显示我们的 fast_car1 对象确实已被 JSON 序列化。

两全其美的

到目前为止,我们已经探索了两种在 Python 中序列化对象的方法:第一种使用模块 pickle 模块和自定义编码器类 json 序列化为 JSON pickle 非常用户友好,但不易于人类阅读且不安全。 json 则相反。

将这两种方法的优点结合起来的艰苦工作已经为我们完成了,并且可以通过巧妙命名的 jsonpickle 模块来实现。该模块提供了一组工具来将复杂的 Python 对象序列化为 JSON,还可以处理反序列化。 jsonpickle 它建立在可 JSON 序列化的基本对象类型之上,并允许序列化更复杂的对象。

获取此模块的最简单方法是使用快速 pip install 命令。 带有 与不要使用它来反序列化来自不受信任来源的数据 pickle . 相同的警告标签 .

它的功能与我们在本文中已经看到的类似,因此我们不会在这里详细介绍。不用说,它带有 encode() 如果您需要更多详细信息和一些快速示例, 请查看 文档

掌握 Python 中的对象序列化

我们希望我们已经揭开了 Python 中对象序列化的神秘面纱。我们向您展示了一些有用的工具,以帮助您更好地管理程序和数据。一定要亲自动手,并尝试这里显示的示例。然后,您将很快掌握 Python 的另一个方面!

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部