如何在PyCharm中使用元编程支持动态类型提示?

问题描述 投票:2回答:3

在PyCharm中,类型提示可以正确支持标准库dataclass。但是,当我使用与mydataclass相同的工具时,PyCharm不能支持:

from dataclasses import dataclass
from typing import Tuple, Dict, TypeVar

_C = TypeVar('_C', bound=type)


class TestORM(type):
    def __new__(cls, clsname: str, bases: Tuple, clsdict: Dict):
        param = ""
        for key, key_type in clsdict.get('__annotations__', {}).items():
            param += f", {key}: {key_type.__name__} = {clsdict.get(key)}"
        clsdict['__init__'] = make_init(param)
        return super().__new__(cls, clsname, bases, clsdict)


@dataclass
class Test:
    a: int = 0


def mydataclass(cls: _C) -> _C:
    param = ""
    for key, key_type in cls.__annotations__.items():
        param += f", {key}: {key_type.__name__} = {getattr(cls, key)}"
    setattr(cls, "__init__", make_init(param))
    return cls


def make_init(param:str):
    locals = {}
    txt = f'def __init__(self{param}):\n   pass'
    exec(txt, None, locals)
    return locals['__init__']


@mydataclass
class MyTest:
    a: int = 0

class MyORMTest(metaclass=TestORM):
    a: int = 0

if __name__ == '__main__':
    Test(a='a')
    MyTest(a='a')
    MyORMTest(a='a')

如何使PyCharm类型提示工作?

总而言之,我只想知道PyCharm如何使用dataclass使用自定义类,而没有任何与自定义类相关的存根文件。当我使用dataclassexec相同的工具使我的__init__函数动态时,我仍然无法得到正确的类型提示。

PyCharm是否进行了一些特定的解析或检查特定的库?

python python-3.x pycharm metaprogramming type-hinting
3个回答
0
投票

Python是一种动态语言。这意味着对象可以是任何东西,并且可以在运行时进行转换。

某些功能,如类型提示,静态分析工作 - 以及Pycharm工具链确实包含了一些类型提示的提示,它们也可以通过静态分析检查Python自己的数据类。静态分析意味着:它不依赖于“实时”数据 - 它通过查看代码并通过与语言分开学习的规则子集进行检查来完成。

简而言之:Pycharm使用的工具没有任何可能的机制可以推断任意动态代码的类型提示。这是不可能的。

如果您要创建一个广泛的框架,您绝对希望在IDE中使用静态类型提示,则必须获取IDE本身使用的工具的来源(我不确定数据类的类型提示是否已完成通过mypy本身或其他工具),并扩展其中一个工具 - 或者创建一个自己的工具,能够以你通常声明的方式内省框架中声明的类型。

否则它就不会发生。


0
投票

这对make_init()来说是一种奇怪的方式。为什么不嫁接一个真正的功能呢?我想PyCharm可能会透过setattr看到,但我打赌它无法通过eval看到。

EG

def make_init():
  def my_init(self, a:int = 1):  # Should be noted by IDE.
    pass
  return my_init

0
投票

您可以使用PEP 561中描述的存根文件。然后是存根文件,您可以添加自动创建文件的签名。

如果pyi文件你添加条目

class MyTest: 
    def __init__(a: int): ...

然后你将在PyCharm中进行类型提示。

但我不知道如何只为文件中的部分条目添加提示。我在这里要求:Partial stub in PyCharm

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