2 ms·
> But typing.Callable has zero support for them, meaning they can’t be typed in a higher-order context. https://peps.python.org/pep-0612/ https://peps.python.o
by Spivak 4y ago
> But typing.Callable has zero support for them, meaning they can’t be typed in a higher-order context.
https://peps.python.org/pep-0612/ https://peps.python.org/pep-0612/
from typing import Awaitable, Callable, ParamSpec, TypeVar
P = ParamSpec("P")
R = TypeVar("R")
def add_logging(f: Callable[P, R]) -> Callable[P, Awaitable[R]]:
async def inner(*args: P.args, **kwargs: P.kwargs) -> R:
await log_to_database()
return f(*args, **kwargs)
return inner
@add_logging
def takes_int_str(x: int, y: str) -> int:
return x + 7
await takes_int_str(1, "A") # Accepted
await takes_int_str("B", 2) # Correctly rejected by the type checker
I think the author and the people working on Python's type annotations actually agree here. The goal is to have type annotations powerful enough to statically describe all behavior generically without library specific extensions. There hasn't been much push for it but I expect a lot of the author's concerns would be alleviated by a type annotation for types themselves. Being able to say, "alright I'm gonna so some dynamic metaprogramming magic bullshit, but at the end will pop out a class of this shape" probably gets you 80% of the way where.