在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
使用自定义类,而没有任何与自定义类相关的存根文件。当我使用dataclass
与exec
相同的工具使我的__init__
函数动态时,我仍然无法得到正确的类型提示。
PyCharm是否进行了一些特定的解析或检查特定的库?
Python是一种动态语言。这意味着对象可以是任何东西,并且可以在运行时进行转换。
某些功能,如类型提示,静态分析工作 - 以及Pycharm工具链确实包含了一些类型提示的提示,它们也可以通过静态分析检查Python自己的数据类。静态分析意味着:它不依赖于“实时”数据 - 它通过查看代码并通过与语言分开学习的规则子集进行检查来完成。
简而言之:Pycharm使用的工具没有任何可能的机制可以推断任意动态代码的类型提示。这是不可能的。
如果您要创建一个广泛的框架,您绝对希望在IDE中使用静态类型提示,则必须获取IDE本身使用的工具的来源(我不确定数据类的类型提示是否已完成通过mypy
本身或其他工具),并扩展其中一个工具 - 或者创建一个自己的工具,能够以你通常声明的方式内省框架中声明的类型。
否则它就不会发生。
这对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
您可以使用PEP 561中描述的存根文件。然后是存根文件,您可以添加自动创建文件的签名。
如果pyi
文件你添加条目
class MyTest:
def __init__(a: int): ...
然后你将在PyCharm中进行类型提示。
但我不知道如何只为文件中的部分条目添加提示。我在这里要求:Partial stub in PyCharm