作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
如何为以下类型定义 Python 协议(protocol):
这是我的尝试:
from typing import Any, Protocol, TypeVar
T = TypeVar("T", covariant=True)
class Operation(Protocol[T]):
def __call__(self, **kwargs: Any) -> T:
pass
# some example functions that should be a structural sub-type of "Operation[str]"
def sumint(*, x: Any, y: Any) -> str:
return f"{x} + {y} = {x + y}"
def greet(*, name: Any = "World") -> str:
return f"Hello {name}"
# an example function that takes an "Operation[str]" as an argument
def apply_operation(operation: Operation[str], **kwargs: Any) -> str:
return operation(**kwargs)
if __name__ == "__main__":
print(apply_operation(sumint, x=2, y=2))
# prints: 2 + 2 = 4
print(apply_operation(greet, name="Stack"))
# prints: Hello Stack
但是,mypy 会产生错误:
example.py:26: error: Argument 1 to "apply_operation" has incompatible type "Callable[[NamedArg(Any, 'x'), NamedArg(Any, 'y')], str]"; expected "Operation[str]"
example.py:28: error: Argument 1 to "apply_operation" has incompatible type "Callable[[DefaultNamedArg(Any, 'name')], str]"; expected "Operation[str]"
Found 2 errors in 1 file (checked 1 source file)
我做错了什么?如何让 MyPy 开心?
最佳答案
您无法定义适合您要求的协议(protocol),因为从静态类型角度来看它根本上是不安全的。
这里的问题是,虽然你说 Operation[T]
的一个实例应该可以“使用任何数量的任何类型的关键字参数”进行调用,您似乎实际上意味着它接受一些关键字参数的组合。它不仅仅接受任何关键字参数。
如果你可以定义一个 Operation[T]
具有您想要的特性的协议(protocol),然后是您的apply_operation
def apply_operation(operation: Operation[str], **kwargs: Any) -> str:
return operation(**kwargs)
仍然是一个类型错误。 operation(**kwargs)
是不安全的,因为不能保证提供的关键字参数是参数 operation
接受。你可以打电话
apply_operation(sumint, name="Stack")
这将适合 apply_operation
签名,但这仍然是一个不安全的调用。
如果你想对此进行注释,最好的选择可能是使用 Callable[..., T]
,正如 Alex Waygood 的回答中所建议的。指定...
作为 Callable
的参数类型列表有效地禁用可调用参数的类型检查,就像用 Any
注释变量一样有效地禁用该变量的类型检查。
请记住,这会禁用安全检查 - 如果您执行类似 apply_operation(sumint, name="Stack")
的操作,则不会发出警告。 .
关于python - 如何为可使用任意数量的 Any 类型的关键字参数调用的类型定义 Python 协议(protocol)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68499904/
我是一名优秀的程序员,十分优秀!