更精确的类型

2023-10-10

在本课中,您将了解Python 3.8 中更精确的类型。 Python 的类型系统目前已经相当成熟。然而,在 Python 3.8 中,输入中添加了一些新功能,以允许更精确的输入:

  • 文字类型
  • 类型化词典
  • 最终对象
  • 协议

Python支持可选类型提示,通常作为代码上的注释:

>>>
>>> def double(number: float) -> float:
...     return 2 * number

在这个例子中,你说number应该是一个浮点数并且double()也应该返回一个浮点数。然而,Python 将这些注释视为提示。它们不会在运行时强制执行:

>>>
>>> double(3.14)
6.28

>>> double("I'm not a float")
"I'm not a floatI'm not a float"

double()愉快地接受"I'm not a float"作为一个参数,即使这不是一个浮点数。

类型提示允许静态类型检查器对 Python 代码进行类型检查,而无需实际运行脚本。这让人想起编译器捕获其他语言中的类型错误,例如爪哇, 和。此外,类型提示充当代码的文档,使其更易于阅读,并且改进 IDE 中的自动完成功能.

笔记:有几种可用的静态类型检查器,包括皮赖特, pytype, 和柴堆。在本课程中,您将使用迈皮。您可以从安装 Mypy皮伊使用pip:

$ python -m pip install mypy

在之前的代码示例中尝试 Mypy。创建一个新文件,名为float_check.py:

# float_check.py

def double(number: float) -> float:
    return 2 * number

double(3.14)

double("I'm not a float")

现在在此代码上运行 Mypy:

$ mypy float_check.py
float_check.py:8: error: Argument 1 to "double" has incompatible
                        type "str"; expected "float"
Found 1 error in 1 file (checked 1 source file)

根据类型提示,Mypy 能够告诉您第 8 行使用了错误的类型。将第二次调用的参数更改为double()到一个float:

# float_check.py

def double(number: float) -> float:
    return 2 * number

double(3.14)

double(2.4)

现在再次在此代码上运行 Mypy:

$ mypy float_check.py
Success: no issues found in 1 source file

从某种意义上说,Mypy 是 Python 类型检查器的参考实现,并且正在被在 Dropbox 开发在 Jukka Lehtasalo 的领导下。 Python 的创建者 Guido van Rossum 是 Mypy 团队的一员。

您可以在 Python 中找到有关类型提示的更多信息原始 PEP 484,以及在Python 类型检查(指南),以及视频课程Python 类型检查.

有四个关于类型检查的新 PEP 已被接受并包含在 Python 3.8 中。您将看到每个示例的简短示例。

公众号 586介绍了文字类型。Literal有点特殊,它代表一个或几个特定值。一个用例Literal当字符串参数用于描述特定行为时,能够精确地添加类型。考虑以下示例:

# draw_line.py

def draw_line(direction: str) -> None:
    if direction == "horizontal":
        ...  # Draw horizontal line

    elif direction == "vertical":
        ...  # Draw vertical line

    else:
        raise ValueError(f"invalid direction {direction!r}")

draw_line("up")

该程序将通过静态类型检查器,即使"up"是无效方向。类型检查器仅检查"up"是一个字符串。在这种情况下,更准确地说,方向必须是文字字符串"horizontal"或文字字符串"vertical"。使用Literal,你完全可以这样做:

# draw_line.py

from typing import Literal

def draw_line(direction: Literal["horizontal", "vertical"]) -> None:
    if direction == "horizontal":
        ...  # Draw horizontal line

    elif direction == "vertical":
        ...  # Draw vertical line

    else:
        raise ValueError(f"invalid direction {direction!r}")

draw_line("up")

通过向类型检查器公开允许的方向值,您现在可以收到有关错误的警告:

$ mypy draw_line.py
draw_line.py:15: error:
    Argument 1 to "draw_line" has incompatible type "Literal['up']";
    expected "Union[Literal['horizontal'], Literal['vertical']]"
Found 1 error in 1 file (checked 1 source file)

基本语法是Literal[<literal>]。例如,Literal[38]代表字面值38。您可以使用以下方式表达多个文字值之一Union:

Union[Literal["horizontal"], Literal["vertical"]]

由于这是一个相当常见的用例,因此您可以(并且可能应该)使用更简单的表示法Literal["horizontal", "vertical"]反而。在添加类型时您已经使用了后者draw_line().

如果仔细查看上面 Mypy 的输出,您可以看到它在内部将更简单的表示法转换为 Union 表示法。

在某些情况下,函数返回值的类型取决于输入参数。一个例子是open(),它可能返回一个文本字符串或一个字节数组,具体取决于mode。这可以通过处理超载.

以下示例显示了一个计算器的框架,它可以将答案返回为常规数字(38)或作为罗马数字 (XXXVIII):

# calculator.py

from typing import Union

ARABIC_TO_ROMAN = [(1000, "M"), (900, "CM"), (500, "D"), (400, "CD"),
                   (100, "C"), (90, "XC"), (50, "L"), (40, "XL"),
                   (10, "X"), (9, "IX"), (5, "V"), (4, "IV"), (1, "I")]

def _convert_to_roman_numeral(number: int) -> str:
    """Convert number to a roman numeral string"""
    result = list()
    for arabic, roman in ARABIC_TO_ROMAN:
        count, number = divmod(number, arabic)
        result.append(roman * count)
    return "".join(result)

def add(num_1: int, num_2: int, to_roman: bool = True) -> Union[str, int]:
    """Add two numbers"""
    result = num_1 + num_2

    if to_roman:
        return _convert_to_roman_numeral(result)
    else:
        return result

该代码具有正确的类型提示:结果add()将是str或者int。但是,通常会使用文字来调用此代码True或者False作为价值to_roman,在这种情况下,您希望类型检查器准确推断是否str或者int被返回。这可以使用以下方法完成Literal和...一起@overload:

# calculator.py

from typing import Literal, overload, Union

ARABIC_TO_ROMAN = [(1000, "M"), (900, "CM"), (500, "D"), (400, "CD"),
                   (100, "C"), (90, "XC"), (50, "L"), (40, "XL"),
                   (10, "X"), (9, "IX"), (5, "V"), (4, "IV"), (1, "I")]

def _convert_to_roman_numeral(number: int) -> str:
    """Convert number to a roman numeral string"""
    result = list()
    for arabic, roman in ARABIC_TO_ROMAN:
        count, number = divmod(number, arabic)
        result.append(roman * count)
    return "".join(result)

@overload
def add(num_1: int, num_2: int, to_roman: Literal[True]) -> str: ...
@overload
def add(num_1: int, num_2: int, to_roman: Literal[False]) -> int: ...

def add(num_1: int, num_2: int, to_roman: bool = True) -> Union[str, int]:
    """Add two numbers"""
    result = num_1 + num_2

    if to_roman:
        return _convert_to_roman_numeral(result)
    else:
        return result

所添加的@overload签名将帮助您的类型检查器推断str或者int取决于字面值to_roman。请注意,省略号 (...) 是代码的文字部分。它们代表重载签名中的函数体。

作为补充Literal, 公众号 591介绍最终的。此限定符指定不应重新分配、重新定义或覆盖变量或属性。以下是打字错误:

# final_id.py

from typing import Final

ID: Final = 1

...

ID += 1

Mypy 将突出显示该行ID += 1,并注意你Cannot分配给final name "ID"。这为您提供了一种确保代码中的常量永远不会改变其值的方法。

此外,还有一个@最终的可以应用于类和方法的装饰器。课程装饰的@final不能被子类化,同时@final方法不能被子类覆盖:

# final_class.py

from typing import final

@final
class Base:
    ...

class Sub(Base):
    ...

Mypy 将使用错误消息标记此示例Cannot inherit from final class "Base"。要了解更多信息Final@final, 看公众号 591.

允许更具体类型提示的第三个 PEP 是公众号 589,其中介绍了类型字典。这可用于使用类似于类型化的表示法来指定字典中键和值的类型命名元组.

传统上,字典是用词典。问题是,这只允许一种类型的键和一种类型的值,通常会导致像这样的注释Dict[str, Any]。例如,考虑一个注册有关 Python 版本信息的字典:

py38 = {"version": "3.8", "release_year": 2019}

对应的值version是一个字符串,而release_year是一个整数。这不能用精确表示Dict。随着新TypedDict,您可以执行以下操作:

# typed_dict.py

from typing import TypedDict

class PythonVersion(TypedDict):
    version: str
    release_year: int

py38 = PythonVersion(version="3.8", release_year=2019)

然后类型检查器将能够推断出py38["version"]有类型str, 尽管py38["release_year"]是一个int。在运行时,一个TypedDict是一个常规的dict,并且类型提示照常被忽略:

>>>
>>> from typed_dict import *
>>> py38
{'version': '3.8', 'release_year': 2019}
>>> type(py38)
<class 'dict'>

如果您的任何值的类型错误,或者您使用尚未声明的键,Mypy 会让您知道。看公众号 589了解更多示例。

Mypy已经支持了协议已经有一段时间了。但是,那正式验收只发生在2019年5月。

协议是一种形式化 Python 对鸭子类型支持的方式:

当我看到一只鸟像鸭子一样走路、像鸭子一样游泳、像鸭子一样嘎嘎叫时,我称那只鸟为鸭子。 (来源)

例如,鸭子打字可以让你阅读.name在任何具有.name属性,而不真正关心对象的类型。对于打字系统来说支持这一点似乎是违反直觉的。通过结构子类型,仍然可以理解鸭子类型。

例如,您可以定义一个名为Named可以识别所有带有a的对象.name属性:

# protocol.py

from typing import Protocol

class Named(Protocol):
    name: str

def greet(obj: Named) -> None:
    print(f"Hi {obj.name}")

class Dog:
    ...

x = Dog()

greet(x)

创建后Named协议,并定义功能greet()这需要一个参数obj,类型提示指定obj遵循Named协议。通过 Mypy 运行代码以查看发现的内容:

$ mypy protocol.py
protocol.py:16: error: Argument 1 to "greet" has incompatible type "Dog"; expected "Named"
Found 1 error in 1 file (checked 1 source file)

Dog类没有属性.name,因此不符合检查要求Named协议。添加一个.name类的属性,带有默认字符串:

# protocol.py

from typing import Protocol

class Named(Protocol):
    name: str

def greet(obj: Named) -> None:
    print(f"Hi {obj.name}")

class Dog:
    name = 'Good Dog'

x = Dog()

greet(x)

跑步protocol.py再次通过Mypy:

$ mypy protocol.py
Success: no issues found in 1 source file

正如你所确认的,greet()接受任何对象,只要它定义了一个.name属性。看公众号 544Mypy 文档有关协议的更多信息。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

更精确的类型 的相关文章

  • Jetson TX2零基础学习(二)——安装pip3、pytorch、torchvision

    目录 一 安装pip3 二 安装pytorch 三 安装torchvision 系列文章 大家好 xff0c 很开心又见面了 xff0c 这次接着上篇博客 xff0c 为大家详细介绍在Jetson TX2中搭环境的方法 一 安装pip3 首
  • Android-推荐一个沉浸式状态栏开源库

    自从android4 4开始 xff0c android手机状态栏再也不是一成黑的时代 xff0c 之前叫做变色龙 xff0c miui6发布会把他叫做沉浸式 xff0c 之后大家就自然而然的接受了沉浸式这个名称 xff0c 其实实际应该叫
  • 详解Linux下使用vscode编译运行和调试C/C++

    vscode是文本编辑而非集成开发环境 需要经过配置才能在其上编译执行代码 本教程将具体详解在linux上配置Visual Studio Code使用GCC C 编译器 g 和GDB调试器的方法 GCC是GNU 编译器集合 GDB则是 GN
  • 83、基于STM32单片机的智能公交报站系统 公交车GPS定位时钟语音报站器

    毕设帮助 开题指导 技术解答 xff08 有偿 xff09 见文末 目录 摘要 一 硬件方案 二 设计功能 三 实物图 四 原理图 五 PCB图 六 硬件框图 七 流程图 八 程序源码 九 资料包括 摘要 本文详细介绍了一款基于STM32单
  • 使用chatgpt 的api,当天就超过了免费试用额度(Free trial usage)

    如果你是ChatGPT的用户,你又是一个开发者,你可以通过
  • ChatGPT赚钱变现的24种方法

    越来越多的人看到了赚钱机会,开始利用 ChatGPT 进行变现。在这篇文章中,我想分享一些高鲸发现的方法。
  • 上架不久Android App,就收到tiktok的侵权警告(Notice of Claimed Infringements)

    我的一个朋友想通过google play市场挣点外快,刚送审不久就通过了“IARC Live Rating Notice”。过几天就收到了tiktok的侵权警告,具体邮件是这样的.
  • 在家赚钱的10种方法

    自由职业者是指那些独立工作并按项目或小时数收费的人,他们不属于任何公司或机构。通过成为自由职业者,你可以在家工作并赚取收入。你可以通过注册类似于Upwork, Freelancer, Fiverr等网站的方式开始你的自由职业者生涯。在这些网
  • 堆栈帧和堆栈跟踪

    A 栈帧代表单个函数调用 您可以将相互调用的函数可视化为彼此堆叠的虚拟框架 这堆数据结构实际上就是用来干这个的 当一个函数调用将其数据返回给调用者时 其堆栈帧将从堆栈中删除 添加和删 除新的堆栈帧 及其相关数据 直到最底部的堆栈帧 有时称为
  • 使用 .format() 方法格式化字符串

    这 format 方法是一种较新的格式化方法 应该优先于 样式格式 在本课程中 您将学习何时应该使用它 如何生成强大的格式字符串而不使简单的用例复杂化 以及如何将 int 变量格式化为十六进制字符串 gt gt gt gt gt gt He
  • 真正的 Python Slack 社区

    社区以及与其他 Python 达人的联系是 Real Python 的一个非常重要的方面 我们最受欢迎的社区功能是私人 Slack 社区 在这里您可以结识 Real Python 团队的其他学生和成员 要了解更多信息 请点击学习Python
  • 关于克劳迪娅·吴

    关于克劳迪娅 吴 Claudia 是一位狂热的 Pythonista 和 Real Python 贡献者 她是一名数据科学家 曾在多家专门从事信用和欺诈风险建模领域的科技初创公司工作 看看她网站欲了解更多出版物 克劳迪娅的教程 如何使用 P
  • Python 基础知识:数字和数学(概述)

    你不需要成为数学高手也能编程得好 事实是 很少 程序员需要了解的不仅仅是基本代数 当然 您需要了解多少数学取决于 您正在开发的应用程序 一般来说 数学水平要求 成为一名程序员的难度比你想象的要低 尽管数学和计算机编程的相关性不如 有些人可能
  • 站点连接检查器

    以下是您可以从中获得灵感的站点连接检查器示例 平命令 关于网络实用程序的维基百科文章 站点24x7 网站监控服务 以下是可用于构建站点连接检查器的资源 要求 一个优雅而简单的 Python HTTP 库 专为人类而构建 使用 Python
  • 使用 Flask 在 Web 上部署 Python 脚本

    您编写了一个令您引以为豪的 Python 脚本 现在您想向世界展示它 但how 大多数人不知道如何处理你的 py文件 将您的脚本转换为Python 网络应用程序是一个很好的解决方案 可以让您的代码可供广大受众使用 在本课程中 您将学习如何从
  • 继承和组合:Python OOP 指南(摘要)

    你探索过Python 中的继承和组合 您了解了继承和组合创建的关系类型 您还完成了一系列练习来了解如何在 Python 中实现继承和组合 在本课程中 您学习了如何 使用继承来表达是一个两个类之间的关系 评估继承关系是否正确 在Python中
  • 自定义数据类型

    当你通过一个目的到print 它使用以下方法将其转换为字符串str 功能 您可以创建一个 str 自定义对象上的方法来更改输出内容 class Person def init self name age self name name sel
  • Python 内部函数的基础知识

    以下是一些资源 可提供有关本课程所涵盖主题的更多信息 在 Python 中递归思考 真正的Python教程 Python 中的递归 简介 真正的Python教程
  • Python 中的条件语句 (if/elif/else)

    在本分步课程中 您将学习如何在 Python 中使用条件 if 语句 逐步掌握 if 语句 并了解如何在程序中编写复杂的决策代码 参加测验 通过我们的交互式 Python 条件语句 测验来测试您的知识 完成后 您将收到一个分数 以便您可以跟
  • 设置您的 Python CI 项目

    在本视频中 您将学习如何设置用于持续集成 CI 的 Python 项目 因此 创建了 GitHub 存储库 克隆了项目并实现了一些基本的库功能 这是calculator py示例代码中使用的文件 calculator py Calculat

随机推荐

  • ChatterBot:使用 Python 构建聊天机器人

    目录 演示 项目概况 先决条件 第 1 步 使用 Python ChatterBot 创建聊天机器人 第 2 步 开始训练您的聊天机器人 第 3 步 导出 WhatsApp 聊天记录 第 4 步 清理您的聊天导出 第 5 步 使用自定义数据
  • 进行日期和时间算术

    Python 标准库提供了timedelta班级用于表演加减在一个datetime目的 第三方库dateutil有更有用的方法来进行数学计算
  • 运行 Python 脚本

    作为 Python 开发人员需要培养的最重要技能之一是能够运行 Python 脚本和代码 这将是您了解代码是否按计划运行的唯一方法 这甚至是了解您的代码是否有效的唯一方法 本分步课程将指导您完成一系列运行 Python 脚本的方法 具体取决
  • 第 2 节审查

    该视频总结了有关装饰器的第 2 部分 您现在知道如何 创建简单的装饰器并将它们应用到函数中 通过使用应用语法糖 装饰你的功能的符号 重用装饰器并将它们导入到您的程序中 用参数修饰函数 从修饰函数返回值 对Python对象进行内省以及如何使用
  • 通过真正的 Python Slack 社区提升您的技能

    目录 享受生活 保持好奇心 提出问题并尊重他人 找到提问的最佳渠道 Spend Some Time Composing Your Questions 总结您的问题 为您的问题提供背景信息 提供一个最小的可重复示例 提供追溯 请勿交叉发帖 尝
  • 处理时区

    Python 3 9 在时区方面引入了重大变化 添加了zoneinfo数据库 在本课程中 您将学习如何使用ZoneInfo类将时区信息添加到datetime目的 您还将探索不一致的命名标准造成的复杂性 如果您想了解有关圣诞岛 基里蒂马蒂示例
  • PyCon Africa 2019(回顾)

    目录 PyCon Africa 发生了什么 主会议 穆斯塔法 西塞 人工智能产生积极影响的潜力 Meili Triantafyllidi 在柏林 PyLadies 工作 6 年的经验教训 Candy Tricia Khohliwe 网络虚拟
  • 第 142 集:使用 Apache Airflow 协调大型和小型项目

    第 142 集 使用 Apache Airflow 协调大型和小型项目 真正的 Python 播客 2023 年 1 月 27 日54m RSS Apple Podcasts Google Podcasts Spotify More 播客瘾
  • Python 新闻:2023 年 3 月以来的新增内容

    目录 Python 3 12 0 Alpha 6 发布 Python 本地包目录上的 PEP 582 被拒绝 PyCascades 2023 在不列颠哥伦比亚省温哥华举行 PyCon US 2023 招募志愿者 PyPI 发布博客 2022
  • 使用Python或运算符

    Python 中有 3 个布尔运算符 and or 和not 使用它们 您可以测试条件并决定程序将采用哪个执行路径 在本教程中 您将深入了解 Pythonor运算符及其使用方法 在本课程结束时 您将学到 Python 如何or操作员工作 如
  • Python F 字符串:讨厌的细节

    您已经了解了很多有关 F 弦的知识以及它们为何如此出色 在本课程中 您将了解在使用以下内部 f 字符串时要记住哪些细节 引号 词典 牙套 反斜杠
  • Python mmap:使用内存映射进行文件 I/O

    这Python之禅有很多智慧可以提供 一个特别有用的想法是 应该有一种 最好只有一种 明显的方法来做到这一点 然而 在 Python 中完成大多数事情有多种方法 而且通常都有充分的理由 例如 有Python 读取文件的多种方法 包括很少使用
  • Python 图形用户界面编程

    Python 图形用户界面编程 学习路径 技能 图形用户界面 GUI Python支持多种GUI框架或工具包 从传统上与 Python 捆绑在一起的 Tkinter 到许多跨平台解决方案 例如 PyQT 或 wxPython 您可以将其作为
  • 第 78 集:通过图解故事学习 Python

    第 78 集 通过图解故事学习 Python 真正的 Python 播客 2021 年 9 月 17 日48m RSS Apple Podcasts Google Podcasts Spotify More 播客瘾君子 灰蒙蒙 袖珍铸件 投
  • Django 测试(第 1 部分)——最佳实践和示例

    目录 Intro to Testing in Django 测试类型 最佳实践 结构 第三方包 Examples 设置 测试模型 测试视图 测试表格 测试 API 下次 测试至关重要 如果没有正确测试您的代码 您将永远不会知道代码现在或将来
  • Python 3.11 预览:TOML 和 tomllib

    目录 Python 3 11 Beta 很酷的新功能 安装 tomllib TOML Parser in Python 3 11 学习基本 TOML 使用 tomllib 读取 TOML 写入TOML Other New Features
  • Python 包版本控制最佳实践

    如果您添加新功能或添加重大更改 您需要更改软件包的版本 在本课程中 您将了解语义版本控制以及如何在项目中使用它 笔记 如果您想了解有关语义版本控制的更多信息 请务必查看semver org
  • 2021 年 7 月 21 日

    本周我们有一位特别嘉宾联合主持人 Real Python 自己的巴托什 扎钦斯基 David 和 Bartosz 联手回答会员的问题 在这次会议上 我们讨论了 Python 新闻和更新 什么是 REST API 有哪些学习它们的好资源 什么
  • 字符串索引

    弦乐是字符数据的有序序列 索引允许您使用数值直接访问字符串中的各个字符 字符串索引是零基础 字符串中第一个字符的索引为 0 下一个字符为 1 依此类推 在本课程中 您将学习字符串索引语法并通过几个示例进行练习 gt gt gt gt gt
  • 更精确的类型

    在本课中 您将了解Python 3 8 中更精确的类型 Python 的类型系统目前已经相当成熟 然而 在 Python 3 8 中 输入中添加了一些新功能 以允许更精确的输入 文字类型 类型化词典 最终对象 协议 Python支持可选类型