无需循环导入的 Python 类型提示

标签 python python-3.5 python-3.4 type-hinting python-typing

我正在尝试将我的庞大类(class)分成两部分;好吧,基本上进入“主”类和具有附加功能的混合,如下所示:

main.py 文件:

import mymixin.py

class Main(object, MyMixin):
    def func1(self, xxx):
        ...

mymixin.py 文件:

class MyMixin(object):
    def func2(self: Main, xxx):  # <--- note the type hint
        ...

现在,虽然这工作得很好,但 MyMixin.func2 中的类型提示当然无法工作。我无法导入 main.py,因为我会得到循环导入,并且如果没有提示,我的编辑器 (PyCharm) 无法判断 self 是什么。

我正在使用 Python 3.4,但如果那里有可用的解决方案,我愿意迁移到 3.5。

有什么方法可以将我的类分成两个文件并保留所有“连接”,以便我的 IDE 仍然为我提供自动完成功能以及来自它了解类型的所有其他好处?

最佳答案

恐怕没有一种非常优雅的方法来处理一般的导入周期。您的选择是重新设计代码以消除循环依赖,或者如果不可行,请执行以下操作:

# some_file.py

from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from main import Main

class MyObject(object):
    def func2(self, some_param: 'Main'):
        ...

TYPE_CHECKING 常量在运行时始终为 False,因此不会评估导入,但 mypy(和其他类型检查工具)将评估那个 block 。

我们还需要将 Main 类型注释制作为字符串,有效地向前声明它,因为 Main 符号在运行时不可用。

如果您使用的是 Python 3.7+,我们至少可以通过利用 PEP 563 来跳过提供显式字符串注释的过程。 :

# some_file.py

from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from main import Main

class MyObject(object):
    # Hooray, cleaner annotations!
    def func2(self, some_param: Main):
        ...

from __future__ import comments 导入将使所有类型提示成为字符串并跳过对它们的求值。这可以帮助我们的代码更加符合人体工程学。

总而言之,将 mixin 与 mypy 一起使用可能需要比您当前拥有的结构更多的结构。迈比 recommends an approach这基本上就是 deceze 所描述的——创建一个由 MainMyMixin 类继承的 ABC。如果您最终需要做类似的事情才能让 Pycharm 的检查器满意,我不会感到惊讶。

关于无需循环导入的 Python 类型提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59876080/

相关文章:

python - 如何使用正确的自动补全功能编辑 Python 脚本?

python - 在 hello world prog 中获取错误消息 'NameError: global name ' kw'未定义'

python - 字典理解中的字典合并

python - 创建和使用模块 "float object not callable"-Python 3.5.1

python - tkinter.Listbox 滚动条 yview

json - 摆脱 JSON 中的 Mongo $ 符号

python - 捕获标准输出时 python2 和 python3 之间的 StringIO 可移植性

python - Django:关闭 http 响应消息的控制台输出

python - 如何在 Pandas.read_csv 中使用方括号作为引号字符

如果满足条件,则修改列表元素的 Pythonic 方法