我正在try 编写一个简单的类型包装器来表示修饰器函数的接口:
from typing import Protocol, TypeVar, Generic
TIn = TypeVar('TIn', contravariant=True)
TOut = TypeVar('TOut', covariant=True)
class Decorator(Protocol, Generic[TIn, TOut]):
"""
Represents a decorated value, used to simplify type definitions
"""
def __call__(self, value: TIn) -> TOut:
...
这将用于键入装饰符函数,如下所示:
IntFunction = Callable[[int, int], int]
def register_operator(op: str) -> Decorator[IntFunction, IntFunction]:
def inner(value: IntFunction) -> IntFunction:
# register the function or whatever
return value
return inner
@register_operator("+")
def add(a: int, b: int) -> int:
return a + b
在上面的示例中,Mypy能够验证add
的类型签名,以确保它与register_operator
的规范匹配.
这对于将类型转换(例如将其从IntFunction
转换为StrFunction
)的修饰符很有用,但在几乎所有情况下,TIn
与TOut
是相同的,因此我想简化我的定义的使用.
从本质上讲,我希望这样做:如果没有给出TOut
,它将被假定为与TIn
相同,这将允许将上面的修饰符函数简化为
def register_operator(op: str) -> Decorator[IntFunction]:
# Simplification here ^
def inner(value: IntFunction) -> IntFunction:
# register the function or whatever
return value
return inner
我在协议定义中使用的理想语法应该是这样的:
class Decorator(Protocol, Generic[TIn, TOut = TIn]):
"""
Represents a decorated value, used to simplify type definitions
"""
def __call__(self, value: TIn) -> TOut:
...
请注意,这不起作用.
我如何才能在继续获得Mypy提供的保证的同时实现此功能?我很高兴根据需要将Decorator
的定义变得复杂,但我想保持其简单的用法.