我有以下内容:
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*"