英文:
Python typing: pylance doesn't show input types
问题
以下是您要翻译的内容:
我正在尝试为任何可调用对象创建“包装器”类。以下是最小示例:
from typing import Any, TypeVar, Generic, Callable
ReturnType = TypeVar("ReturnType", bound=Any)
CallableType = Callable[..., ReturnType]
class Wrapper(Generic[ReturnType]):
def __init__(self, callable_: CallableType[ReturnType]) -> None:
self.callable_ = callable_
def __call__(self, *args: Any, **kwargs: Any) -> ReturnType:
return self.callable_(*args, **kwargs)
class Action:
def __init__(self, title: str) -> None:
"""docstring"""
self.title = title
wrapped = Wrapper(Action)
action = wrapped("title")
Pylance 可以理解 `action` 的类型是 `Action`,但我看不到 `__init__` 文档字符串和所需的参数:
期望的行为:
我做错了什么,如何修复?
英文:
I'm trying to do "wrapper" class for any callable. Here is minimal example:
from typing import Any, TypeVar, Generic, Callable
ReturnType = TypeVar("ReturnType", bound=Any)
CallableType = Callable[..., ReturnT]
class Wrapper(Generic[ReturnType]):
def __init__(self, callable_: CallableType[ReturnType]) -> None:
self.callable_ = callable_
def __call__(self, *args: Any, **kwargs: Any) -> ReturnType:
return self.callable_(*args, **kwargs)
class Action:
def __init__(self, title: str) -> None:
"""docstring"""
self.title = title
wrapped = Wrapper(Action)
action = wrapped("title")
Pylance can understand, that action
type is Action
, but I can't see __init__
docsting and needed arguments:
What do I do wrong and how can I fix it?
答案1
得分: 1
你已经用Any
注释了你的__call__
方法,但Pyright不会根据你的使用情况来限制这些Any
的更具体类型。你需要使用ParamSpec来捕获可接受为参数的可调用对象的参数(类似于你如何使用TypeVar来捕获返回类型)。
from typing import Any, TypeVar, ParamSpec, Generic, Callable
Params = ParamSpec("Params")
ReturnType = TypeVar("ReturnType")
class Wrapper(Generic[Params, ReturnType]):
def __init__(self, callable_: Callable[Params, ReturnType]) -> None:
self.callable_ = callable_
def __call__(self, *args: Params.args, **kwargs: Params.kwargs) -> ReturnType:
return self.callable_(*args, **kwargs)
class Action:
def __init__(self, title: str) -> None:
"""docstring"""
self.title = title
wrapped = Wrapper(Action)
action = wrapped("title")
注意1:如果你使用的是Python < 3.10,你需要从typing_extensions
中导入ParamSpec
。
注意2:你不需要传递bound=Any
给TypeVar,因为那基本上是默认的。传递bound=Any
不会改变任何东西。
英文:
You've annotated your __call__
with Any
. Pyright doesn't restrict these Any
to more narrow types just based on your usage. You'll need to use a ParamSpec to capture the parameters of the callable you accept as the argument (similar how you capture the return type with a TypeVar).
from typing import Any, TypeVar, ParamSpec, Generic, Callable
Params = ParamSpec("Params")
ReturnType = TypeVar("ReturnType")
class Wrapper(Generic[Params, ReturnType]):
def __init__(self, callable_: Callable[Params, ReturnType]) -> None:
self.callable_ = callable_
def __call__(self, *args: Params.args, **kwargs: Params.kwargs) -> ReturnType:
return self.callable_(*args, **kwargs)
class Action:
def __init__(self, title: str) -> None:
"""docstring"""
self.title = title
wrapped = Wrapper(Action)
action = wrapped("title")
Note1: If you're using python<3.10 you'll need to import ParamSpec
from typing_extensions
.
Note2: You don't need to pass a bound=Any
to the TypeVar as that's (more or less) the default anyway. Passing bound=Any
doesn't change anything nevertheless.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论