Python 的 Self 类型 | 注释返回 Self 类型的参数2024年8月29日 | 阅读 8 分钟 有时,我们在庞大的 Python 代码库中迷失方向,难以跟踪变量的预期类型。类型提示和注释在这种情况下可以帮助覆盖变量类型。在本教程中,我们将讨论返回自身或类其他实例的注释方法。我们在上一教程中已经讨论了各种类型的注释和方法。 如何在 Python 中使用 Self 类型注释函数从 Python 3.11 及更高版本开始,PEP 673 定义的 Self 类型是返回类实例的函数的推荐注释。Self 类型可以直接从 `typing` 模块导入。 但是,对于 3.11 之前的 Python 版本,Self 类型在 `typing_extensions` 模块中可用。您可以从那里导入它,用于注释返回类实例的函数。 以下是如何导入和使用 Self 类型的示例 示例 - 在这两种情况下,Self 类型都用作 `self` 参数的注释以及函数的返回类型。这表明该函数返回一个属于其自身的类实例。 请注意,对于 3.11 之前的 Python 版本,如果 `typing_extensions` 包未安装,我们将需要安装它。我们可以使用 pip 安装它: 通过使用 Self 类型,我们可以为返回类实例的函数提供清晰简洁的注释,从而提高代码的可读性和可维护性。 现在,让我们看一下表示银行账户状态和逻辑的类的结构。BankAccount 类包含各种选项,例如存入和取出资金,这些操作会更新账户状态并返回类实例。让我们理解以下示例。 示例 - Self 类型用作返回类实例的函数的注释。 `@dataclass` 装饰器应用于 BankAccount 类,以根据定义的字段自动生成 `__init__`、`__repr__`、`__eq__` 等特殊方法的默认实现。 我们可以创建一个 BankAccount 对象并如下使用函数: 上面的代码创建了一个 BankAccount 对象,其账号为 123456,初始余额为 1000.0 卢比。然后它显示账户余额,存入 500.0 卢比,取出 200.0 卢比,并再次显示更新后的余额。 使用 Self 类型可以实现函数链式调用,从而在对 BankAccount 对象执行多个操作时实现简洁可读的代码。 Self 类型也可以用于类方法和继承层级结构。例如,如果父类和子类具有返回自身的函数,我们可以用 Self 类型注释两者。 我们正在创建一个继承自 BankAccount 的 SavingsAccount 类。 示例 - `create_from_application` 函数是一个类方法(用 `@classmethod` 装饰),它根据提供的初始存款和利率创建 SavingsAccount 对象。它使用 `random.randint` 函数生成一个随机的七位数账号,然后实例化并返回一个新的 SavingsAccount 类实例,其中包含生成的账号、初始存款和利率。 `calculate_interest()` 函数根据当前余额和利率计算储蓄账户的利息。它将余额乘以利率除以 100,然后返回计算出的利息。 `add_interest()` 函数将计算出的利息添加到储蓄账户。它调用 `calculate_interest()` 函数来确定利息金额,然后使用 `deposit` 函数(可能从 BankAccount 类继承)将利息添加到账户余额。最后,它返回 self,从而可以进行函数链式调用,并在向账户添加利息时实现简洁的代码。 我们现在可以使用 `create_from_application()` 函数创建一个 SavingsAccount 对象。 使用 TypeVar 注释注释返回类实例的函数的另一种方法是利用 TypeVar。TypeVar 代表一个类型变量,它在类型检查期间充当特定类型的占位符。它通常用于处理泛型类型,例如指定特定对象的列表,如 `list[str]` 或 `list[BankAccount]`。 通过使用 `TypeVar`,您可以定义一个代表当前类的类型变量,并将其用作返回该类实例的函数的注释。这允许更灵活和通用的类型注释。 以下是一个示例来说明这种方法。 示例 - 在此示例中,T 是使用 TypeVar 定义的类型变量。它代表当前类,允许进行通用注释。 `some_method()` 函数用 T 作为返回类型进行注释,表示它返回类的实例。 通过以这种方式使用 TypeVar,您可以为返回类实例的函数提供更通用和灵活的类型注释。 一个受类约束的 TypeVar 可以实例化为该类的任何子类。此功能在 BankAccount 和 SavingsAccount 示例的上下文中特别有用。 示例 - 正如我们所看到的,TBankAccount 被绑定到 BankAccount,现在我们可以正确地注释在 BankAccount 中返回自身的函数。 解释 - 在上面的代码中,我们用 TBankAccount 注释了 `.display_balance()` 以指定它将返回类实例。关键是要记住 TBankAccount 与 BankAccount 不同。它仅用于在无法直接使用 BankAccount 的注释中表示 BankAccount 类型。 出于多种原因,Self 类型通常优于 TypeVar。TypeVar 的主要缺点之一是它可能很冗长,导致更复杂的类型注释。开发人员也可能意外地忘记实例化 TypeVar 或正确地将其绑定到类,从而导致潜在的类型相关问题。 另一方面,Self 类型(在 Python 3.11 中引入,并在早期版本中可在 typing_extensions 中使用)提供了更简单、更简洁的语法。它明确地将类实例表示为返回类型,从而无需使用 TypeVar。 Self 类型提高了代码的可读性,并降低了与类型注释相关的错误或疏忽的风险。它还享有更好的 IDE 支持,因为大多数现代 IDE 都可以理解并根据 Self 类型提供准确的建议。 考虑到这些原因,Self 类型通常比 TypeVar 更受青睐,用于注释返回类实例的函数,因为它具有直观简洁的语法、提高的代码可读性和更好的 IDE 支持。 使用 `__future__` 模块Python 的 `__future__` 模块提供了各种方法来注释返回封闭类的函数。有时,此模块用于引入与未来 Python 版本兼容的不兼容更改。 注释可以使用大于 3.7 的 Python 版本导入。让我们理解以下示例。 示例 - 在上面的代码中,我们从 `__future__` 模块导入了注释。此模块在低于 3.7 的版本中不可用。我们直接使用类名作为 `.push()` 的注释。 使用 `future` 模块使用类名注释函数不被认为是最佳实践,因为它不如使用 Self 类型直观和 Pythonic。此外,必须记住在脚本开头从 future 导入可能会很麻烦。而且,值得注意的是,在用 future 注释时,继承的支持不足。 使用字符串进行类型提示注释返回类实例的函数的另一种选择是使用字符串。此方法推荐用于 3.7 之前的 Python 版本或当其他方法均不适用时。字符串注释不需要任何导入,并且被大多数静态类型检查器广泛识别。 示例 - 在这种情况下,在字符串注释中包含类名很重要。省略类名将导致静态类型检查器无法将返回类型识别为有效的 Python 对象。字符串注释直接实现了与 `__future__` 注释的后台功能类似的结果。 字符串注释的一个重要限制是它们在继承期间不会保留其信息。当子类从超类继承函数时,超类中指定的字符串注释不会自动转移到子类。因此,如果您依赖字符串注释进行类型提示或文档记录,则必须在每个子类中声明注释。此过程可能容易出错且耗时。 结论在 Python 中使用类型提示和注释可以提高代码的可读性和可维护性,特别是当代码变得更大、更复杂时。通过指定变量、函数参数和返回值的类型,您可以帮助其他开发人员理解预期的变量类型以及函数调用的预期结果。 Self 类型是一种特定的类型提示,可用于注释返回自身类实例的函数。通过使用 Self 类型,返回类型变得显式,这在防止继承和子类化期间可能发生的细微错误方面可能是有利的。尽管可以使用 TypeVar、`__future__` 模块和字符串等替代方法来注释返回类实例的函数,但建议在可行的情况下使用 Self 类型。 下一主题追踪鸟类迁徙 |
组合科学中的一个排列组合的错排是其组成部分出现在其原始位置的组成部分。例如,对于序列 [1, 2, 3, 4],一个错排将是 [2,...
阅读 4 分钟
您可以使用 Advanced Python Scheduler (APScheduler) Python 包来安排您的 Python 代码稍后运行,一次或多次。您可以灵活地根据需要添加新任务和删除旧任务。如果您的作业能够经受住调度程序重启并保持其状态,那么您将...
阅读 6 分钟
? NLP,即自然语言处理,已成为理解和分析人类交流的强大工具。由于机器学习和深度学习的发展,NLP 变得更加复杂,从而在各个领域实现了各种应用。NLP 可能会改变我们收集、检查和使用临床数据的方式……
21 分钟阅读
Python 中模块和包的区别 许多程序员和业余程序员经常会混淆模块和包。问题通常出现在很难确定何时何地应该实现模块或包时。在下文中……
阅读 2 分钟
在 Python 中,有多种方法可以计算列表中项的出现次数。计算元素在列表中出现的次数是处理数据时经常需要的一项基本操作。无论是识别最频繁的...
5 分钟阅读
人脸检测是在图像或视频中识别人类面部的过程。它是计算机视觉领域一个快速发展的领域,提供了各种有用的应用程序,例如安全系统、人脸识别和图像分析。本文将探讨可以...
阅读 19 分钟
在本教程中,我们将学习 Python 中的 currying,这是一个在 Python 中比较新的概念。大多数开发者可能不熟悉这个主题。我们将解释 currying 的概念、它的用例以及如何在 Python 中实现它。让我们开始……
阅读 6 分钟
JSONB 是 PostgreSQL 中一种强大的数据类型,它提供了一种灵活的方式来存储和查询半结构化数据。在许多应用程序中,JSONB 列用于存储需要频繁更新的复杂数据结构。在本文中,我们将讨论如何更新...
阅读 6 分钟
Python 中“==”和“is”运算符的区别 在 Python 中比较对象时,身份运算符通常用于应使用相等运算符 == 的地方。在实践中,在尝试比较数据时使用 is 很少是一个好主意。身份运算符...
阅读 3 分钟
性能分析是一种重要的分析形式,我们可以利用它来分析代码的时间或空间复杂度。像 Python 这样的编程语言提供了各种库来满足性能分析的目的。一些用于分析时间复杂度的性能分析库示例可以是...
阅读 8 分钟
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India