带有可变数量的str /相同类型参数的Callable的Python类型提示?

时间:2019-08-26 13:28:09

标签: python python-3.x python-typing

如何为所有这些可调用对象指定一种类型:

a(str)
b(str, str)
c(str, str, str)
d(str, str, str, str

我发现我可以以一般方式指定Callable[..., None],但如何详细指定所有参数都将是str而不使用丑陋的语法Union[Callable[[str], None], Callable[[str, str], None, __more_like_this__]。还有其他方法吗?我可以使用打字来做到吗?

2 个答案:

答案 0 :(得分:4)

您可以使用callback protocol来指定带有可变字符串参数的函数类型:

from typing_extensions import Protocol


class Callback(Protocol):
    def __call__(self, *args: str) -> None: ...

并像这样使用它:

def handler(cb: Callback) -> None:
    cb('a', 'b', 'c')

def callback(*args: str) -> None:
    pass

handler(callback)

请注意,回调函数必须采用可变参数,例如。这行不通:

def callback(a: str, b: str) -> None:
    pass

协议已在Python 3.8中添加到标准库typing模块中,因此,如果要在Python 3.5-3.7上使用它们,则需要从PyPI安装typing-extensions模块。

答案 1 :(得分:0)

您想要的是4种不同类型的并集。

t1 = Union[
 Callable[[str],Any],
 Callable[[str,str],Any],
 Callable[[str,str,str],Any],
 Callable[[str,str,str,str],Any],
]

与可以接受1-4个参数的函数类型进行比较:

t2 = Callable[[str,Optional[str],Optional[str],Optional[str]],Any]

类似

的功能
def foo(x: str, y:str):

不属于上面的第二种类型。如果我说我需要类型t2的函数,那么您不知道我可能尝试传递多少个参数。我可以给您foo,但是您可以尝试传递3个参数或仅传递1个参数,并获得TypeError

如果您要求使用类型为t1的功能,我可以给您foot1不会保证t1中的所有值可以多于或少于正好3个参数;它只包含要做的值。