Python 打字模块中的重载修饰符不';Don’我的行为似乎不像预期的那样
为什么调用的Python 打字模块中的重载修饰符不';Don’我的行为似乎不像预期的那样,python,python-3.x,overloading,strong-typing,Python,Python 3.x,Overloading,Strong Typing,为什么调用的hello(1)使用字符串参数调用函数?理想情况下,@重载操作符应该处理它,对吗?不幸的是,python不允许函数重载。每次您认为您是在重载函数时,您只是在覆盖前面的函数声明。引自: @重载装饰器允许描述 支持多种不同的参数类型组合。一系列 @重载修饰定义后面必须紧跟一个 非重载修饰定义(对于相同的函数/方法)最新版本 @重载修饰定义是为了该类型的利益 仅限checker,因为它们将被 非重载修饰定义,而后者用于 运行时,但应被类型检查器忽略。在运行时,调用 @直接重载修饰函数将引发
hello(1)
使用字符串参数调用函数?理想情况下,@重载
操作符应该处理它,对吗?不幸的是,python不允许函数重载。每次您认为您是在重载函数时,您只是在覆盖前面的函数声明。引自:
@重载装饰器允许描述
支持多种不同的参数类型组合。一系列
@重载修饰定义后面必须紧跟一个
非重载修饰定义(对于相同的函数/方法)最新版本
@重载修饰定义是为了该类型的利益
仅限checker,因为它们将被
非重载修饰定义,而后者用于
运行时,但应被类型检查器忽略。在运行时,调用
@直接重载修饰函数将引发NotImplementedError
键入.重载的正确用法如下:
>>> from typing import overload
>>> @overload
... def hello(s: int):
... return "Got an integer!"
>>> def hello(s: str):
... return "Got a string"
要显示键入的实际好处。重载
允许更改def hello(s:int)
以返回int
,而不是str
:
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))
注意,实际实现仍然返回str
——python在这里不执行任何检查。但是,PyCharm提出了一个警告:
mypy
还抱怨无效类型:
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'
输入模块的目的是允许第三方工具对代码执行静态检查。这里没有什么神奇之处——所有类型在运行时都会被忽略
➜ mypy test.py
test.py:25: error: Unsupported operand types for + ("int" and "str")
蟒蛇>
小绿平托
小红克尔维特你需要修饰这两个定义,否则你只是用一个普通函数重写了hello
中的任何内容。准确地说,应该只修饰存根函数。调用修饰函数将引发NotImplementedError
。重载
的思想是用实际的实现覆盖存根。那么如果我们要检查类型,@重载
有什么意义呢?编辑:没有意义。明白了。我怀疑的原因是Pycon的一次谈话,演讲者做了问题中提到的事情。奇怪。@saruftw请检查更新的答案。简而言之,输入
模块(尤其是在@重载
中)的要点是允许第三方工具(例如mypy)运行静态检查。谢谢你的解释。
# 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))