Python typing: Pylance不显示输入类型

huangapple go评论85阅读模式
英文:

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:Python typing: Pylance不显示输入类型

Desired behaviour:Python typing: Pylance不显示输入类型

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(&quot;Params&quot;)
ReturnType = TypeVar(&quot;ReturnType&quot;)


class Wrapper(Generic[Params, ReturnType]):
    def __init__(self, callable_: Callable[Params, ReturnType]) -&gt; None:
        self.callable_ = callable_

    def __call__(self, *args: Params.args, **kwargs: Params.kwargs) -&gt; ReturnType:
        return self.callable_(*args, **kwargs)


class Action:
    def __init__(self, title: str) -&gt; None:
        &quot;&quot;&quot;docstring&quot;&quot;&quot;
        self.title = title


wrapped = Wrapper(Action)

action = wrapped(&quot;title&quot;)

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.

huangapple
  • 本文由 发表于 2023年6月26日 19:17:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76556174.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定