【发布时间】:2021-10-15 09:12:33
【问题描述】:
简介
我有一个名为 fun(start, stop, divisors) 或 fun(stop, divisors) 的函数。
- 我想按这个特定的顺序调用参数。
- 我想以一种不会出现任何类型提示错误的方式实现它。
如果我放宽这两个限制中的任何一个,实施起来就很容易。例如,放宽对订单的限制可以这样做:
def fun(stop: int, divisors: List[int], start: int=0) -> int:
...
return 0
fun(5, [1, 2, 3])
fun(5, [1, 2, 3], start=2)
或对类型提示的缓和显示在下面的文件中,但参数的顺序正确。
问题
我应该如何编写我的代码,以便我的函数参数是:
- 静态类型;
-
按特定顺序:
(start[optional], stop, divisors); - 给出 0 个 mypy 错误?
尝试
import typing
from typing import Union, Optional
Start = int
Stop = int
Divisor = int
Divisors = list[Divisor]
@typing.overload
def fun1(x: Start, y: Stop, divisors: Divisors) -> int:
...
@typing.overload
def fun1(y: Stop, divisors: Divisors) -> int:
...
def fun1(*args) -> int:
if (arglen := len(args)) not in [2, 3]:
raise TypeError("Function expected 2 or 3 arguments, got", arglen)
if arglen == 2:
args = [0] + list(args)
start, stop, divisors = args
return 0
def fun2(x, y, divisors) -> int:
if divisors is None:
start, stop, divisors = 0, x, y
else:
start, stop = x, y
return 0
def fun3(*args) -> int:
if (arglen := len(args)) == 3:
start: Stop = args[0]
stop: int = args[1]
divisors: Divisors = args[2]
elif arglen == 2:
start: Stop = 0
stop: int = args[0]
divisors: Divisors = args[1]
else:
raise TypeError(
f"Too {'few' if arglen == 0 else 'many'} values to unpack (2-3), got",
arglen,
)
return 0
def fun4(*args) -> int:
if (arglen := len(args)) == 3:
pass
elif arglen == 2:
args = [0] + list(args)
else:
raise TypeError(
f"Too {'few' if arglen == 0 else 'many'} values to unpack (2-3), got",
arglen,
)
start: Stop = args[0]
stop: int = args[1]
divisors: Divisors = args[2]
return 0
typing_test_PE_001.py:20: error: Overloaded function implementation does not accept all possible arguments of signature 1
typing_test_PE_001.py:20: error: Overloaded function implementation does not accept all possible arguments of signature 2
typing_test_PE_001.py:24: error: Incompatible types in assignment (expression has type "List[int]", variable has type "Tuple[Any, ...]")
typing_test_PE_001.py:43: error: Name "start" already defined on line 39
typing_test_PE_001.py:44: error: Name "stop" already defined on line 40
typing_test_PE_001.py:45: error: Name "divisors" already defined on line 41
typing_test_PE_001.py:58: error: Incompatible types in assignment (expression has type "List[int]", variable has type "Tuple[Any, ...]")
Found 7 errors in 1 file (checked 1 source file)
【问题讨论】:
-
def fun(arg1: int, arg2: Union[int, List[int]], arg3: Optional[int] = None)? -
只要你用 Python 编写代码,你就永远不会得到静态类型的函数参数。您的 easy implementation 示例比您可能得到的任何答案都更具可读性和 Pythonic。
-
@Woodford 你可以在 Python 中使用类型提示和像
mypy这样的类型检查器进行静态类型检查 -
@juanpa.arrivillaga 是的,但它不会在运行时强制执行。
-
@Woodford 嗯?静态类型检查不应该在运行时强制执行。
标签: python python-3.x type-hinting mypy python-typing