python、动态类型提示和 pycharm 自动完成

问题描述 投票:0回答:1

我正在尝试让 pycharm 的自动完成功能与 python 中的动态类型提示一起使用。假设我们有一个描述符,它在

__init__
上采用“类型”参数并将值转换为
__set__
上的该类型:

import typing as t

_type = t.TypeVar('_type')

class CastDescriptor:
    def __init__(self, type: t.Type[_type]):
        self.type = type

    def __set_name__(self, owner, name):
        self.name = name

    def __get__(self, obj, _) -> _type | 'CastDescriptor':
        if obj is None:
            return self
        return obj.__dict__[self.name]

    def __set__(self, obj, value):
        obj.__dict__[self.name] = self.type(value)


class Test:
    a = CastDescriptor(dict)
    
    def __init__(self, a):
        self.a = a

test = Test(a=[(1, 2)])
print(test.a) # prints {1:2}

上面的代码工作得很好,但是 pycharm 无法识别属性

test.a
是一个字典,所以自动完成不适用于该属性。

到目前为止我发现的唯一工作方式是显式复制类型

class Test:
    a: dict[int, int] = CastDescriptor(dict)
    
    def __init__(self, a):
        self.a = a

test = Test(a=[(1, 2)])
test.a.strip() # will be highlited as dict has no attribute 'strip'

不确定是否可行,但如何向 pycharm 显示作为参数传递给描述符的最终属性类型?

python pycharm annotations type-hinting python-descriptors
1个回答
0
投票

这里我将演示:

  • 如何使用Generic正确键入描述符
  • Pycharms 目前使用类型的限制

TypeVars 与普通变量的作用域不同。这意味着即使您在

__init__
__get__
中使用相同的,根据 Pycharm 类型检查器,它们也不被认为是相关的。将 Generic 添加到描述符定义将解决此问题。

class CastDescriptor(t.Generic[_type]):

这可以通过在pycharm中执行以下操作来确认。

class Test:
    a = CastDescriptor(dict)
    b = CastDescriptor(int)
    a.__get__().    # Pycharm autocomplete gives options for dict
    b.__get__().    # Pycharm autocomplete gives options for int

这更接近所需的行为,但

test.a
仍未被识别为
dict
我这样测试:

test.a = [(1, 2)]
test.a.    # Pycharm autocomplete gives options for list
test.a = {1, 2}
test.a.    # Pycharm autocomplete gives options for set

即使使用 OP 的显式类型提示解决方案,也可以看到相同的行为。我们有理由相信类型检查器会忽略描述符。

使用Python3.10、Pycharm 2022.3确认的例子

© www.soinside.com 2019 - 2024. All rights reserved.