如何在赋值时保持类型提示尽管有变量类型注解
我正在写一个叫做 Lazy
的类,它的功能类似于 partial
,但是多了一些额外的功能。这个类的目的是通过将对象包裹在 Lazy
类中来预先初始化一个对象,然后通过调用 to_eager
来完成初始化,用户可以在这个过程中提供一些额外的参数。现在的问题是,在IDE中如何保留类型提示。
下面是代码
from typing import Callable, Generic, ParamSpec, Type, TypeVar
T = TypeVar("T")
P = ParamSpec("P")
class Lazy(Generic[T, P]): # Any makes it ok to asign to any other type
def __init__(
self, cls: Type[T] | Callable[P, T], *args: P.args, **kwargs: P.kwargs
):
self.cls = cls
self.args = args
self.kwargs = kwargs
def to_eager(self, *args: P.args, **kwargs: P.kwargs) -> T:
assert not args
kwg = {**self.kwargs, **kwargs}
return self.cls(*self.args, **kwg)
class SomeClass:
def __init__(self, y: int = 1):
self.y = y
l = Lazy(SomeClass, y=5)
l.to_eager() # here VSCode hints me with (y: int -> 1)
当我尝试调用 to_eager()
时,我能看到关于原始类可能的参数的提示。
现在的问题是,如果这和变量类型赋值结合在一起会出现什么情况
l: Lazy = Lazy(SomeClass, y=5)
l.to_eager() # type hint is gone, I get (... -> Unknown)
这个问题可以稍微改善一下
l: Lazy[SomeClass, ...] = Lazy(SomeClass, y=5)
l.to_eager() # I get (... -> SomeClass)
但是这样做并没有包含参数。
我的问题是 - 在这种情况下,如何在进行变量类型赋值的同时保留参数的类型提示?类型赋值是必要的,比如当我把它和数据类结合使用时。也许 pyright
有什么配置可以避免类型扩展?或者也许 vscode 有什么有用的选项?
我到目前为止尝试过的:
- 将
P
作为第二个参数传递给Lazy[SomeClass, P]
,但得到了警告,提示P
在这个上下文中没有意义,而且 VSCode 也没有类型提示。
1 个回答
1
Lazy
单独使用时,相当于 Lazy[Any, Any]
,这会覆盖 Lazy[SomeClass, int]
推断出的类型。这里的“懒惰”其实是指没有明确指定类型提示,这样编辑器就无法提供参数提示。
...
本身被认为是 types.EllipsisType
的简写。
你希望的是编辑器能够支持某种类型变量绑定的概念,这样你就可以写一个“类型”,它的值会被传递给 Lazy
的实际参数所绑定,类似于
l: Lazy[Cls, T] = Lazy(SomeClass, y=5)
这样 Cls
和 T
就可以(也许仅在这个赋值中)分别绑定到 SomeClass
和 int
。