如何在协议中包含 args 和 kwargs?

问题描述 投票:0回答:1

我正在尝试编写协议以确保给定函数包含初始参数。如果我使协议定义仅支持该单个参数,mypy 会很高兴,但是当我添加

*args
**kwargs
以支持其他任意参数时,mypy 会抱怨。

from typing import Protocol, TypeVar, Dict, Any

T = TypeVar("T", covariant=True)

class Func(Protocol[T]):
    def __call__(self, ctx: Dict[Any, Any], *args: Any, **kwargs: Any) -> T:
        pass

def f(ctx: Dict[Any, Any]) -> str:
    return "hello"

def ff(ctx: Dict[Any, Any], *args: Any, **kwargs: Any) -> str:
    return "hello"

a: Func[str] = f  # mypy complains here
b: Func[str] = ff # but not here

这可能吗?或者有没有办法告诉 mypy 只检查第一个参数而不检查其余参数的存在?

我不想使用

Callable[..., T]
因为它不强制执行
ctx
参数。

-- 编辑

我正在寻找这种行为:

def f(ctx: Dict[Any, Any]) -> str:
    return "hello"

def ff(ctx: Dict[Any, Any], x: int) -> str:
    return "hello"

def fff(ctx: Dict[Any, Any], x: int = 0) -> str:
    return "hello"

def ffff(x: int) -> str:
    return "hello"

a: Func[str] = f    # yes
b: Func[str] = ff   # yes
c: Func[str] = fff  # yes
d: Func[str] = ffff # no

函数定义可以包含任意数量的附加参数,只要第一个参数是

Dict
.

python mypy python-typing
1个回答
0
投票

Mypy 抱怨是因为如果一个变量的类型是

Func[str]
:

a: Func[str] = f

那么逻辑上你应该能够做到:

a({'the answer': 42}, 1, 2, 3, other_stuff="hello")

因为

Func
的接口指定它接受任意参数。

你的

f
函数没有,所以它不符合
Func
.

你真正想做的是使

Func
more的签名更严格:

class Func(Protocol[T]):
    def __call__(self, ctx: Dict[Any, Any]) -> T:
        pass

f
ff
都可以用这个签名调用,所以他们都符合
Func
.

© www.soinside.com 2019 - 2024. All rights reserved.