当前位置: 首页 > 工具软件 > Overload > 使用案例 >

Python模块Typing.overload的使用

劳和雅
2023-12-01

一、 使用场景

Python3 >= 3.5

当一个函数被定义了规定的输入或输出的规定的数据类型时(即Function Annotation函数注解功能),只能输入或输出规定的 静态数据类型 。那么如果传入其他类型的数据时就会报错,如下:

def test(name: str) -> str:
    return f"hello {name}"

test(1)

>>> ... TypeError: must be str, not int

但这是运行时的错误,也就是代码在执行时才会发现问题。最好是我们能在写完代码时就发现是否存在问题。因此就有了类型检查工具,比如mypy这样的工具,还有很多IDE也集成了这样的检查工具。

那么如果就需要使用该函数,又需要输入或输出 动态数据类型 怎么办呢,所以引入了overload。

二、实现动态语言

解决以上问题又两种方案:

  • 1、使用typing.TypeVar
  • 2、使用typing.overload

2.1 TypeVar

先说第一种,对于固定数量参数的方法而言,同一个参数如果打算接受多种类型,可以这么用,比方说参数可以是:int, float, str:

from typing import TypeVar

T = TypeVar('T', int, float, str)

def test(name: T) -> str:
    return f"hello {name}"

test(2)

这种方案更类似于静态语言中的interface的概念,定义一个通用的父类,这样的话,你可以传递子类型过去。

2.2 overload

overload翻译过来是 重载 的意思,Java中有这样的两个概念,重写(override)和重载(overload)。重写其实是在保证输入和输出不变的情况下重写实现逻辑。而重载则是允许修改输入和输出,即同一个方法名可以支持多种类型的输入和输出。

跟静态语言中还是很有差别的。

from typing import overload

@overload
def test(name: str) -> str:
    ...
    
@overload
def test(name: float) -> str:
    ...

@overload
def test(name: int, age: int) -> str:
    ...
    
def test(name, age=18):
     return f"hello {name}"

test(2)

通过定义多个同名函数,上面的同名函数需要通过overload装饰器装饰。可以看到被装饰的函数的输入类型和输出类型都可以更改。但是,最后一定要定义一个没有装饰器的同名函数 才能实现动态的效果。

这么用的作用是什么呢?文档中有一句话很重要:

“The @overload-decorated definitions are for the benefit of the type checker only, since they will be overwritten by the non-@overload-decorated definition, while the latter is used at runtime but should be ignored by a type checker. ”

翻译:被overload装饰的函数仅仅是为了受益于类型检查工具,因为它们会被没有overload装饰的函数定义覆盖,尽管未被装饰的函数是用于运行时的,但是会 被类型检查工具忽略

所以,看到这应该明白了,overload仅仅是给检查工具用的。但如果静态类型检查变成工程的一部分的话,这也会避免很多问题,在写代码时也会比心里有底。

 类似资料: