我写了一个python模块:
b.py
class B:
pass
a.py
from b import B
class A:
def __init__(self):
self.member: B = B()
__init__.py
from ab_package.a import A
from ab_package.b import B
我使用极简主义的setup.py
文件将其打包并安装在pip中
setup(
name='ab_package',
version='0.0.1',
description='My AB package',
url='https://github.com/somewhere',
author='Me',
author_email='me@somedomain.com',
license='Private',
packages=['ab'],
install_requires=['numpy>=1.19.5',
'pandas>=1.3.3',
'pylint==2.11.1',
'pyparsing~=2.4.7',
'requests~=2.26.0',
'wget~=3.2',
],
classifiers=[
],
)
然后在另一个项目中,我使用它:
from ab_package import A, B
a = A()
myvar = a.member
问题是在PyCharm中,myvar
被推断为Any
。
我可以修复显式类型提示myvar
,但这不够简洁(尤其是当我的类型比B
长得多时(。
我怎样才能使推理按预期进行?
在您显示的示例代码中,推断b
的类型为Any
是一个更严重问题的症状,即当您尝试在赋值语句中查找a.b
时,将得到一个AttributeError
。类型检查器mypy
正确地将其标识为错误,正如您在这里看到的那样。我不确定PyCharm的内置类型检查在这里会有什么不同,尽管我希望它也能识别错误。
如果您更改了代码,使您在A.__init__
中创建的B
实例成为一个属性,那么代码就会起作用,并且可以推断类型,至少可以通过mypy:推断
class B:
pass
class A:
def __init__(self):
self.b: B = B() # change member to self.b here
a = A()
b = a.b
reveal_type(b) # type checker reports __main__.B for me, should be ab_package.b.B for you
正如@Blckknht所说,问题来自于在包中Python文件之间的相对导入。
如果我只是在b
的导入中添加一个点,使其成为a.py
中的from .b import B
,那么a.member
具有正确的推断类型(以及myvar
(。
a.py
from .b import B
class A:
def __init__(self):
self.member: B = B()