如何键入提示二阶装饰工/装饰工工厂(PEP-612 ParamSpec)



我有以下内容:

T = TypeVar("T")
P = ParamSpec("P")

class GeneratorLen(Generic[T]):
def __init__(self, gen: Iterator[T], length: int):
self.gen = gen
self.length = length
def __len__(self) -> int:
return self.length
def __iter__(self) -> Iterator[T]:
return self.gen

def sized(
length: int,
) -> Callable[Callable[P, Iterator[T]], Callable[P, IterableAndSized[T]]]:  # ERROR
def _makesized(
func: Callable[P, Iterator[T]],
) -> Callable[P, IterableAndSized[T]]:
@functools.wraps(func)
def wrapper(*args: P.args, **kwargs: P.kwargs) -> IterableAndSized[T]:
return GeneratorLen(func(*args, **kwargs), length)
return wrapper
return _makesized

sized装饰器可用于向迭代器添加__len__属性,以向len()等函数提示其长度。

然而,mypy给出了一个错误:TIO

main.py:37: error: The first argument to Callable must be a list of types or "..."

这是尚未实现还是我做错了什么?使用mypy最新(0.931(

Close,只是缺少Callable:参数周围的一对括号

def sized(
length: int,
) -> Callable[[Callable[P, Iterator[T]]], Callable[P, IterableAndSized[T]]]:
...

也许一个更清晰的最小示例:

from __future__ import annotations
from typing import *
P = ParamSpec("P")
R = TypeVar("R")
def add_logging(name: str) -> Callable[[Callable[P, R]], Callable[P, R]] :
def outer(func: Callable[P,R]) -> Callable[P,R]:
def inner(*args: P.args, **kwargs: P.kwargs) -> R:
result = func(*args, **kwargs)
print(f"Hello {name}: {result}")
return result
return inner
return outer

@add_logging("world")
def foo(x:int, y: str) -> float:
print(f"got {x=}, {y=}")
return 1.0


reveal_type(foo)  # Revealed type is "def (x: builtins.int, y: builtins.str) -> builtins.float*"

最新更新