首页 > 编程问答 >如何使类装饰器对 Pylance 友好?

如何使类装饰器对 Pylance 友好?

时间:2024-07-28 07:12:30浏览次数:4  
标签:python python-typing pylance

我正在使用 pylance 并启用 严格模式 ,并希望获得更好的开发体验。

它工作得很好,直到我定义了一些 类装饰器

def struct(cls : Type[Any]) -> Type[Any]:
    # ... do some magic here ...
    return dataclass(frozen=True)(cls)

@struct
class Vec:
    x: int
    y: int

print(Vec(1, "abc")) # no error msg here, no hints about constructor arguments also.

这里,当我输入 Vec( 时,没有关于构造函数参数类型的提示,当我输入 Vec(1, "abc") 时,没有发生类型错误。

并且我发现将 @struct 定义为泛型函数(而不是使用 Any)使事情变得更糟:

A = TypeVar("A")

def struct(cls : Type[A]) -> Type[A]:
    # ... do some magic here ...
    return dataclass(frozen=True)(cls)

@struct
class Vec:
    x: int
    y: int

print(Vec(1, 2)) # type error here: Expected no arguments to Vec

在这种情况下,当我输入 Vec(1, 2) 时,会发生类型错误,并且显示“Expected no arguments to Vec”,这不是预期的。|| |我希望有某种方式可以

告诉 pylance (或其他静态 linter)有关返回类的 元信息 (可能通过 从原始类生成,但我承诺,返回的类的元数据在此之后不会动态修改)。 typing.get_type_hints 我注意到 pylance 可以很好地处理

,所以我认为可能有 @dataclass 某种机制| ||来实现​​这一点。 有什么办法可以做到这一点吗?或者 只是经过pylance特殊处理的?

Is there any way to do that? or @dataclass is just special processed by pylance?


遇到的问题是 Pylance(以及 MyPy 等其他类型检查器)难以推断出类装饰器的返回类型,尤其是在涉及运行时类型操作时。

以下是一些可以使的类装饰器对 Pylance 更友好的方法:

1. 使用 typing.cast 进行类型断言:

虽然这不是最优雅的解决方案,但它简单有效。可以使用 typing.cast 告诉 Pylance 装饰器返回的类型:

from typing import TypeVar, Type, Any, cast
from dataclasses import dataclass

A = TypeVar("A")

def struct(cls: Type[A]) -> Type[A]:
    # ... do some magic here ...
    dataclass_cls = dataclass(frozen=True)(cls)
    return cast(Type[A], dataclass_cls)

@struct
class Vec:
    x: int
    y: int

print(Vec(1, 2))  # Now Pylance should recognize the constructor arguments

2. 使用 __post_init__ 初始化数据类属性:

与其在装饰器中使用 dataclass(frozen=True) ,不如在类定义中使用它,并在 __post_init__ 方法中初始化冻结的属性:

from typing import TypeVar, Type, Any
from dataclasses import dataclass, field

A = TypeVar("A")

def struct(cls: Type[A]) -> Type[A]:
    # ... do some magic here ...
    return cls

@struct
@dataclass(frozen=True)
class Vec:
    x: int
    y: int

    def __post_init__(self):
        # ... 在此处进行任何必要的初始化 ...

print(Vec(1, 2))  # Pylance 应该能够推断出构造函数参数

3. 使用自定义元类:

可以定义一个自定义元类,它在创建类时应用的逻辑,并确保类型提示正确传播:

from typing import TypeVar, Type, Any

A = TypeVar("A")

class StructMeta(type):
    def __new__(cls, name, bases, attrs):
        # ... 在此处应用的逻辑 ...
        return super().__new__(cls, name, bases, attrs)

class Vec(metaclass=StructMeta):
    x: int
    y: int

print(Vec(1, 2))  # Pylance 应该能够推断出构造函数参数

请注意,这些方法各有优缺点,需要根据具体情况选择最适合的方法。

不幸的是, @dataclass 装饰器确实经过 Pylance 特殊处理,以提供更好的类型推断。 虽然目前没有直接的方法可以获得与自定义类装饰器相同的级别,但这三种方法可以帮助提高 Pylance 对的代码的理解,并提供更好的开发体验.

标签:python,python-typing,pylance
From: 73413556

相关文章

  • 当读取字节时,Python 将 \n 解释为 0xd0
    换行符被解释为Ð(0xd0)而不是(0x0a),我真的不知道如何解决这个问题。我也不知道从哪里开始。当尝试使用此代码时,它将0x0a读为0xd0。withopen(path,"rb")asroot:b_arr=root.read()+b""print("Processing...")buffer=""b_arr......
  • 在Python 3中获取范围的特定形式
    当获取range(1,100)时,我得到:[1,2,3,4,5...99]我需要像这个范围的zip之类的东西:[50,49,51,48,52,47,53...99]如何获取它?背景:这都是关于比特币谜题66的。首先我做了对过去已知的私钥进行线性回归预测,直到第65题为止。我......
  • Python:如何使用pyaudio或sounddevice等库进行自动录音?
    我想做一个项目,需要满足以下录音要求:程序启动后,会在后台不断检测麦克风的声音,当声音分贝大于一定值时打开录音流级别,当分贝低于一定级别时关闭录音流并保存为wav文件。我知道原理,但我无法使用这些库来实现。我想实现以上结果使用Python实现自动录音以下代......
  • 当我们创建一个在 https 服务器上获取和发送数据的 python 应用程序时,我们应该如何处
    python脚本使用Urllib3,我的服务器是在Node.js上编写的脚本。我担心(并且不清楚)证书:我是否需要将我的python应用程序上的证书另存为变量?例如我这样做了,http=urllib3.PoolManager(cert_reqs="CERT_REQUIRED",ca_certs='client-cert.pem')并且我不知道......
  • 使用 Python 进行 Web 抓取以获取数据 NoneType ERROR
    我正在努力为我的学校项目获取美元和价格。所以我决定为此使用网络抓取,但我有一个问题。当我尝试在服务器上使用我的代码时,它给我NoneType错误。它可以在googlecolab上使用,但我无法在我的电脑或服务器上使用。我该如何解决这个问题?网页抓取代码;defdolar():he......
  • Python 请求 - response.json() 未按预期工作
    我正在尝试从Python的requests模块调用API。在邮递员上,返回的响应标头中的Content-Type是application/json;charset=utf-8,响应json数据是我期望的样子。但是,在python上的API的get方法之后运行response.json()会抛出错误simplejson.errors......
  • Python 中的“样板”代码?
    Google有一个Python教程,他们将样板代码描述为“不幸的”,并提供了以下示例:#!/usr/bin/python#importmodulesusedhere--sysisaverystandardoneimportsys#Gatherourcodeinamain()functiondefmain():print'Hellothere',sys.argv[1]#Command......
  • Python 3.9.1 中的 collections.abc.Callable 是否有 bug?
    Python3.9包含PEP585并弃用typing模块中的许多类型,转而支持collections.abc中的类型,现在它们支持__class_getitem__例如Callable就是这种情况。对我来说,typing.Callable和collections.abc.Ca......
  • 列表子类的 Python 类型
    我希望能够定义列表子类的内容必须是什么。该类如下所示。classA(list):def__init__(self):list.__init__(self)我想包含键入内容,以便发生以下情况。importtypingclassA(list:typing.List[str]):#Maybesomethinglikethisdef__init__(self):......
  • Python 中类型友好的委托
    考虑以下代码示例defsum(a:int,b:int):returna+bdefwrap(*args,**kwargs):#delegatetosumreturnsum(*args,**kwargs)该代码运行良好,只是类型提示丢失了。在Python中使用*args,**kwargs来实现​​委托模式是很常见的。如果有一种方法可......