打字模块中的重载装饰器似乎不像预期的那样

sar*_*ftw 4 python overloading strong-typing python-3.x

>>> from typing import overload

>>> @overload
... def hello(s: int):
...     return "Got an integer!"

>>> def hello(s: str):
...     return "Got a string"
Run Code Online (Sandbox Code Playgroud)

为什么调用者hello(1)使用字符串参数调用函数?理想情况下,@overload操作员应该处理它,对吗?

awe*_*oon 10

不幸的是,python 不允许函数重载。每次你认为你正在重载函数时,你只是覆盖了之前的函数声明。来自文档的引用:

@overload 装饰器允许描述支持多种不同参数类型组合的函数和方法。一系列@overload-decorated 定义必须紧跟一个非@overload-decorated 定义(对于相同的函数/方法)。@overload-decorated 定义仅用于类型检查器,因为它们将被非 @overload-decorated 定义覆盖,而后者在运行时使用但应被类型检查器忽略。在运行时,直接调用@overload-decorated 函数会引发 NotImplementedError。

的正确用法typing.overload如下:

from typing import overload


@overload
def hello(s: int) -> str:
    ...


@overload
def hello(s: str) -> str:
    ...


def hello(s):
    if isinstance(s, int):
        return "Got an integer!"
    if isinstance(s, str):
        return "Got a string"
    raise ValueError('You must pass either int or str')


if __name__ == '__main__':
    print(hello(1))
Run Code Online (Sandbox Code Playgroud)

为了显示typing.overload让更改def hello(s: int)返回int而不是返回的实际好处str

from typing import overload


@overload
def hello(s: int) -> int:
    ...


@overload
def hello(s: str) -> str:
    ...


def hello(s):
    if isinstance(s, int):
        return "Got an integer!"
    if isinstance(s, str):
        return "Got a string"
    raise ValueError('You must pass either int or str')


if __name__ == '__main__':
    print(hello(1))
    a = hello(1) + 1
    b = hello(1) + 'a'
Run Code Online (Sandbox Code Playgroud)

请注意,实际实现仍会返回str- python 不会在此处执行任何检查。但是,PyCharm 提出了警告:

在此处输入图片说明

mypy 还抱怨无效类型:

? mypy test.py 
test.py:25: error: Unsupported operand types for + ("int" and "str")
Run Code Online (Sandbox Code Playgroud)

typing模块的目的是允许第三方工具对您的代码进行静态检查。这里没有魔法——所有类型在运行时都会被忽略。

  • @saruftw 请检查更新的答案。简而言之 - “typing”模块(特别是“@overload”)的要点是允许第 3 方工具(例如 mypy)运行静态检查 (3认同)
  • 为什么不直接使用`Union[str, int]`来表明该函数可以获取 int 或 str 呢? (3认同)
  • 第二个示例中有 2 个重载:`(int) -> int` 和 `(str) -> str`,这不能用 `Union` 来完成 (2认同)

whe*_*cks 7

# tested in Python 3.8.5 32-bit
# overloads the method
# imports libraries from the base distribution 
# confuses some linters
# undermines type-hinting by documenting *kwargs or dispatch signature

from functools import singledispatch

class Car:
    def __init__(self, color: str, brand: str) -> None:
        self.color = color
        self.brand = brand


@singledispatch
def describe_car(color: str, kind: str) -> str:
    return "Little " + color + " " + kind

@describe_car.register(Car)
def _(car: Car) -> str:
        return describe_car(car.color, car.brand)


newcar = Car("red", "corvette")

print(describe_car("green", "pinto"))
print(describe_car(newcar))
Run Code Online (Sandbox Code Playgroud)

pythonout>
小绿色斑托
小红色护卫舰