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

L.G*_*ian 5 python metaprogramming type-hinting pycharm python-3.x

在 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')
Run Code Online (Sandbox Code Playgroud)

PyCharm 中的实际结果

我该怎么做才能使 PyCharm 类型提示工作?

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

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

jsb*_*eno 2

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

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

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

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

否则它就不会发生。