类型注解和 mypy:构建可靠的 Python 代码库的基石

前言

我们都知道python是动态类型语言,让我们专注于代码实现功能,不用关心太多类型问题,但在实际开发中,有很多问题是与类型相关的,这篇文章我们就讨论如何让动态类型拥有静态类型语言才有的能力?

类型注解

类型注解是一种给函数参数、返回值以及任何变量增加类型描述的技术,规范的注解可以大大提升代码可读性。 看这样一段没有类型注解的代码

python 复制代码
def update_data(table, data, where):
    """update sql statement"""
    sql = f"update {table} set "
    sql += dict_to_str(data)
    if where:
        sql += f"where {dict_to_str_and(where)};"
    execute_sql(sql)

如果不深入去看函数的作用,根本不知道传什么类型的参数,我们稍加改动,增加类型注解

python 复制代码
def update_data(table: str, data: Dict, where: Dict) -> None:
    """update sql statement"""
    sql = f"update {table} set "
    sql += dict_to_str(data)
    if where:
        sql += f"where {dict_to_str_and(where)};"
    execute_sql(sql)

这是不是清晰多了,一眼就知道参数需要传什么类型。

typing是类型注解用到的主要模块:

  • List: 列表类型,如ListTuple\[str, int],列表中每个元素是一个包含字符串和整数的元组
  • Tuple: 用于表示元组,例如 Tuple[str, int] 表示包含字符串和整数的元组。
  • Set: 用于表示集合,例如 Set[str] 表示字符串集合。
  • Dict: 用于表示字典,例如 Dict[str, int] 表示键为字符串,值为整数的字典。
  • Optional: 用于表示可选类型,例如 Optional[str] 表示可能为字符串或者 None 的类型。
  • Any: 表示任何类型,相当于取消了类型检查。
  • Union: 用于表示多种可能的类型,例如 Union[str, int] 表示可能为字符串或整数的类型。
  • Callable: 用于表示可调用对象的类型,例如 Callable[[int, int], int] 表示接受两个整数参数并返回整数的可调用对象类型。
  • Iterable: 用于表示可迭代对象的类型,例如 Iterable[int] 表示整数可迭代对象。
  • Generator: 用于表示生成器对象的类型,例如 Generator[int, None, None] 表示生成整数的生成器对象类型。
  • ContextManager: 用于表示上下文管理器对象的类型。
  • Type: 用于表示类对象的类型。
  • NewType: 用于创建新的类型,可以增加代码的可读性和安全性。
  • TypeVar: 用于声明泛型类型变量,例如 T = TypeVar('T')

默认情况下,可以把Python中的类型注解当成一种用于提升代码可读性的注释,只提升代码的说明性,不会对程序的执行过程产生影响。像下面这样

python 复制代码
def update_data(table: str) -> None:
    """update sql statement"""
    sql = f"update {table} set "
    return sql
​
​
update_data(1)

虽然我们指定table的类型为字符串,但是传入整数类型也不会报错。

但是,如果我们引入静态类型检查工具,类型注解就不仅仅是注解了,会对程序正确性产生积极的影响。

这里笔者使用mypy

mypy

mypy 是一个流行的静态类型检查器,用于对 Python 代码进行类型检查。它可以在开发过程中帮助发现潜在的类型错误,并提供更好的代码质量保证。

安装 mypy:

pip install mypy

还是上面那段代码,我们执行mypy demo.py,会输出如下内容

lua 复制代码
demo.py:4: error: No return value expected  [return-value]
demo.py:7: error: Argument 1 to "update_data" has incompatible type "int"; expected "str"  [arg-type]
Found 2 errors in 1 file (checked 1 source file)

mypy找这些类型错误又快又准,不用真正运行代码。在大型项目中,使用类型注解配合mypy进行静态检查,可以轻松找到代码隐藏的问题。

小妙招

可以批量检测py文件,像这样 find . -name "*.py" -exec mypy {} \;

最后

typing+mypy完美搭档,提前发现类型相关问题,提高代码质量、可读性、可维护性。

相关推荐
葫芦和十三5 小时前
图解 MongoDB 07|索引类型:七种索引,七种访问形状
后端·mongodb·agent
兵慌码乱6 小时前
基于Python+PyQt5+SQLite的药房管理系统实现:事务一致性与界面解耦全流程解析
python·sqlite·信号与槽·pyqt5·数据库设计·桌面应用开发·事务处理
朦胧之7 小时前
AI 编程-老项目改造篇
java·前端·后端
金銀銅鐵7 小时前
[Python] 体验用欧几里得算法计算最大公约数的过程
python·数学
爱勇宝10 小时前
我做了一个只用来搜歌词的小 App
android·前端·后端
IT_陈寒11 小时前
SpringBoot自动配置坑了我一晚上,原来问题出在这
前端·人工智能·后端
FreakStudio11 小时前
W55MH32L-EVB 上手测评:硬件 TCP/IP 加持的以太网单片机,MicroPython 零门槛开发
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
SelectDB11 小时前
Litefuse 开源并推出单进程轻量模式,25 秒就能跑起来的 Agent 可观测与评估平台
运维·后端·自动化运维
SelectDB11 小时前
秒级弹性、最高降本 70%:SelectDB Serverless 如何重塑云数仓资源效率
大数据·后端·云原生
PinkSun12 小时前
Spring AI ChatMemory踩坑实录:重启丢数据、Agent丢记忆、对话溢出
后端·ai编程