Python 中的面向数据编程2024年8月29日 | 阅读 10 分钟 在本教程中,我们将学习 Python 中的数据导向编程(DOP),作为传统的面向对象编程(OOP)的替代方案。顾名思义,我们实践的是一种将数据置于首位的编程方法。 我们可以通过遵循四个原则来实现这一目标。这些原则与语言无关。它们可以在面向对象编程语言(Java、C++ 等)、函数式编程(FP)语言(Clojure 等)或通用语言(Python、JavaScript)中表示。让我们了解以下原则。 原则 1:将代码与数据分离在第一个原则中,我们需要以函数行为不依赖于函数上下文中封装的数据的方式编写函数。在 Python 中使用此原则的自然方法是使用顶级函数和仅包含数据字段的数据类。让我们了解以下示例。 示例 - `calculate_name()` 函数不仅可以用于作者,还可以用于用户、图书管理员或任何具有名字和姓氏的个人。通过将负责计算全名的代码与与作者数据创建相关的代码分离,`calculate_name()` 函数可以轻松地在不同实体之间重用。这种设计提供了灵活性并促进了代码重用,使该函数能够在需要根据名字和姓氏生成全名的地方使用。 这种方法的好处是代码可以在不同的上下文环境中重用。 让我们看看不遵循原则 1 的以下示例。 示例 - 解释 - 在上面的代码中,`full_name()` 方法驻留在 `Customer` 类中,我们需要实例化 `Contact` 对象,这需要为每个属性(包括电子邮件和电话)赋值。这只是为了测试一个方法而进行的不必要的复杂而繁琐的设置。 另一方面,在 DOP 版本中,为了测试 `calculate_name()` 代码,我们可以单独创建要传递给函数的数据。 原则 2:用通用数据结构表示数据根据此原则,数据使用通用数据结构表示,例如映射(或字典)和数组(或列表)。在本文中,我们使用 dataclass,它比 DOP 更接近 OOP。Python 的 dataclass 是一种多功能构造,弥合了面向对象编程(OOP)和数据导向编程(DOP)之间的差距。与字典和元组不同,dataclass 具有多项优势,包括减少拼写错误的可能性、通过类型提示提高可读性、简化嵌套复杂结构的表示等等。此外,dataclass 提供了在需要时轻松将实例转换为字典或元组的灵活性。 通过利用 dataclass,我们可以利用 OOP 的优势,例如封装和代码组织,同时利用数据结构简洁和描述性的特性。dataclass 中的类型提示支持有助于确保更好的代码质量,并促进更轻松的调试和维护。此外,将 dataclass 实例转换为字典或元组的固有能力允许与代码库中期望这些数据结构的其他部分或外部系统进行无缝互操作。 让我们理解下面的例子。 示例 - 输出 'first_name': 'Robert', 'last_name': 'Downey', 'n_books': 500} 上述通用结构有助于使用 Python 内置的丰富函数集(适用于 dict、list、tuple 等)来操作数据。 Python 的 dataclass 使我们免于单个类方法的复杂性,使我们能够专注于核心功能。它确保了与不同库版本的兼容性,并最大限度地减少了语言级别更改的影响。这种抽象层促进了代码稳定性,提高了可重用性,并简化了开发和维护过程。 当我们以通用形式定义数据时,这意味着我们可以在需要时进行修改,这是通用数据的一个优势。 在以下示例中,所有字典可能具有不同的键。额外的键可以存在于第二个字典中。 在 Python 中,检索类成员的值和访问字典中与键关联的值之间的性能差异很小。与 Java 等语言不同,Python 没有编译步骤,无法专门针对类成员访问进行编译器优化。因此,这些操作的性能特征通常是可比的。 另一方面,由于其作为哈希表的底层实现,Python 中的字典访问效率很高。根据键从字典中检索值涉及快速查找过程,该过程针对性能进行了优化。 与列表和元组相比,Python 中的集合和字典提供更高效的查找时间。哈希函数的使用允许直接访问数据,从而实现常数时间查找复杂性。相反,列表和元组需要线性搜索,导致查找操作的线性时间复杂性。 当数据作为类的实例创建时,类定义包含有关数据结构的信息。这意味着可以通过检查类轻松识别预期的数据形状。类级别的数据模式的存在有助于发现和理解数据的预期结构。 另一方面,当数据使用通用数据结构(例如字典或列表)表示时,数据模式不作为数据表示的一部分固有包含。数据的结构和预期形状必须单独推断或记录,使其可能不那么明显或可发现。 例如,我们可以轻松定义作为类对象实例化的 `FullName` 的数据形状。让我们看看以下示例。 示例 - 但是,上面的类没有确认它期望的数据形状。假设我们错误地将存储名字的字段输入为 `first_name`。我们将收到一个错误 `TypeError: __init__() got an unexpected keyword argument 'first_name'`。 另一方面,如果我们使用通用数据结构并错误输入字段名,这可能不会抛出错误或异常。相反,结果中会省略名字。 我们将得到以下输出 - None Prat 原则 3:数据是不可变的根据此原则,数据永远不应更改或为可变数据。为了应用此原则,我们使我们的数据冻结。 Python 内置的不可变数据类型有 int、float、decimal、bool、string、tuple 和 range。请注意,dict、list 和 set 是可变的。 可变性的好处是我们都可以自信地访问。处理可变数据时,将其作为参数传递给函数时务必谨慎,因为它有可能被修改或复制。 在给定示例中,最初将空列表作为默认参数传递给函数。但是,由于列表的可变性,每次调用函数时,列表都会经历修改,导致在后续调用中使用了不同的默认值。 让我们理解以下示例 - 示例 - 输出 [1] [1, 2] [1, 2, 3] 我们可以使用以下代码。 示例 - 输出 [1] [2] [3] 我们得到了预期的结果,因为 `None` 是不可变的。当我们使用不可变数据时,它可以毫无顾虑地传递给任何函数,因为数据永远不会改变。 它有助于获得可预测的代码行为。让我们了解以下示例。 示例 - `dict1` 的年龄值是不可预测的。它取决于我们在偶数天还是奇数天运行代码。 然而,对于不可变数据,可以保证数据永远不会改变。让我们看看以下示例。 示例 - 当我们运行上面的代码时,我们将收到错误 `dataclasses.FrozenInstanceError: cannot assign to field "roll_nu"`。冻结的数据类不允许更改 `student_data.roll_nu`,无论它是偶数天还是奇数天。 另一个好处是快速相等性检查。Python 提供了两个用于确定两个对象是否相等的运算符:“is”和“==”。“is”运算符通过检查对象是否驻留在相同的内存地址来比较对象的标识,而“==”运算符通过检查对象中存储的实际内容来比较它们值是否相等。 示例 - 如所提供的示例所示,“is”和“==”运算符在比较不可变数据类型(例如字符串,其值无法更改)时表现出相似的行为。但是,当应用于可变数据类型(例如列表)时,它们的行为有所不同。 在比较不可变数据对象时,“is”运算符往往表现得更一致。这是因为它检查对象的内存地址,提供了一种可靠的方法来确定它们在内存中是否是同一对象。另一方面,“==”运算符检查对象中存储的实际内容以评估它们的相等性。 在性能方面,“is”运算符通常比“==”运算符更快。这是因为比较对象地址比比较对象中的所有单个字段更快。不可变数据允许通过引用而不是内容比较数据来高效进行相等性检查。 在多线程环境中,当数据可变时,可能会导致潜在的竞态条件失败。竞态条件是指两个或多个线程尝试同时访问和修改相同数据,从而导致不可预测的结果。 例如,让我们考虑一个场景,其中两个线程同时尝试访问和修改变量“x”的值,通过向/从其中加/减 10。在这种情况下,由于线程执行的非确定性交错,可能会出现竞态条件。线程可能会同时读取“x”的值,执行各自的操作,然后相互覆盖更改,从而导致不正确的结果或意外的行为。 原则 4:将数据模式与数据表示分离下面是一个简单的 JSON 模式(本质上是一个字典),它指定了表示为另一个字典的数据的结构。该模式概述了所需的字段及其各自的数据类型。另一方面,数据使用通用数据结构表示。 示例 - 数据验证函数(或库)可用于检查一段数据是否符合数据模式。 示例 - 当数据无效时,`validate()` 函数返回带有详细信息的错误,否则通过。 在 Python 中,我们可以允许类成员是可选的。因此,此优点在 Python 上下文中并不强烈。例如,我们可以将 `roll_number` 的默认参数设置为 `None` 以指示该字段是可选的。 示例 - 此原则允许在运行时进行数据验证。它允许定义超出字段类型的数据验证条件。 如果我们将上面的模式与给定的模式进行比较,我们可以为每个字段定义更多的属性。 通过采用数据导向编程 (DOP) 的原则和技术,Python 开发人员可以提高他们编写更易于维护和扩展的代码的能力,从而充分发挥其数据的潜力。 下一主题什么是 PyDev |
红黑树 红黑树是一种二叉搜索树,具有“几乎”平衡的额外属性。红黑树中的每个节点都有一个颜色,红色或黑色,这些颜色用于在插入和删除期间保持平衡。删除:BST 删除:开始于...
阅读 10 分钟
在本教程中,我们将学习如何使用 Python 显示任何年份任何月份的日历。在下面的代码中,我们将导入“calendar”模块。它有一个内置的“month()”函数,该函数接受用户想要查看的年份和月份...
阅读 2 分钟
类方法、静态方法和实例方法之间的区别 在本教程中,我们将学习类方法、静态方法和实例方法。这些方法是 Python 中面向对象编程的核心概念。每个 Python 爱好者都应该熟悉这些方法以及如何...
5 分钟阅读
在本教程中,我们将讨论队列的基本概念和内置的 Queue 类,并使用 Python 代码实现它。什么是队列?队列是一种线性数据结构,用于按顺序存储数据。队列的概念基于……
7 分钟阅读
在本教程中,我们将学习一种流行且广泛使用的行业标准数据交换格式 REST API。它是最常用的数据交换技术。我们将解释如何使用 Django 在 Python 中创建 REST API。在深入探讨之前……
阅读 19 分钟
简介 求解线性方程是 Python 简化的一项基本数学运算。ax + by = c,其中 a、b 和 c 是常数,表示线性方程(或最高幂为 1 的方程)。求解线性方程时,主要目标是...
阅读 3 分钟
在本教程中,我们将学习使用普通哈希函数进行排序。我们熟悉各种排序算法,如堆排序、冒泡排序、合并排序等。这里我们将使用哈希数组对给定元素数组进行排序。然而,...
7 分钟阅读
Python 是一种高级、著名的解释型编程语言,由 Guido van Rossum 于 1991 年推出。截至 2022 年,Python 的需求量很大。Web 设计、数据处理、深度学习、信息科学、数据可视化、脚本编写以及其他领域都使用 Python。Python 是一种多功能且易于学习的计算机……
7 分钟阅读
在 Python 中,与使用其他编程语言相比,转换元素非常容易。在本教程中,我们将讨论将十六进制字符串转换为十进制字符串的不同方法。方法 1:通过使用 int() 函数 int() 函数用于执行这些类型的任务,其...
阅读 3 分钟
Python 允许文件操作(创建、保存、读取、写入、删除文件等等)。Python 简化了多种文件格式的保存,并保存了多种文件格式。JSON 是 JavaScript 对象表示法。数据通过基于文本的计算机语言脚本(可执行)文件存储和发送。Python 的 json 模块支持 JSON。JSON...
阅读 3 分钟
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India