gpt4 book ai didi

python - mypy如何使用typing.TYPE_CHECKING解决循环导入注解问题?

转载 作者:行者123 更新时间:2023-12-03 21:14:47 30 4
gpt4 key购买 nike

我有一个包的以下结构:

/prog
-- /ui
---- /menus
------ __init__.py
------ main_menu.py
------ file_menu.py
-- __init__.py
__init__.py
prog.py
这些是我的导入/类语句:
prog.py :
from prog.ui.menus import MainMenu
/prog/ui/menus/__init__.py :
from prog.ui.menus.file_menu import FileMenu
from prog.ui.menus.main_menu import MainMenu
main_menu.py :
import tkinter as tk
from prog.ui.menus import FileMenu

class MainMenu(tk.Menu):

def __init__(self, master: tk.Tk, **kwargs):
super().__init__(master, **kwargs)
self.add_cascade(label='File', menu=FileMenu(self, tearoff=False))

[...]
file_menu.py :
import tkinter as tk
from prog.ui.menus import MainMenu

class FileMenu(tk.Menu):

def __init__(self, master: MainMenu, **kwargs):
super().__init__(master, **kwargs)
self.add_command(label='Settings')

[...]
这将导致序列中的循环导入问题: prog.py -> __init__.py -> main_menu.py -> file_menu.py -> main_menu.py -> [...]
通过多次搜索,建议将导入更新为:
file_menu.py
import tkinter as tk
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from prog.ui.menus import MainMenu

class FileMenu(tk.Menu):

def __init__(self, master: 'MainMenu', **kwargs):
super().__init__(master, **kwargs)
self.add_command(label='Settings')

[...]
我已阅读 TYPE_CHECKING docsmypy docs关于用法,但我不了解使用此条件如何解决循环。是的,在运行时它可以工作,因为它的计算结果为 False所以这是一个“操作解决方案”,但它在类型检查期间如何不会重新出现:

The TYPE_CHECKING constant defined by the typing module is False at runtime but True while type checking.


我对 mypy 了解不多,因此我看不到条件计算结果如何 True该问题不会再次出现。 “运行时”和“类型检查”之间有什么不同? “类型检查”的过程是否意味着代码没有被执行?
备注:
  • 这不是循环导入依赖问题,因此不需要依赖注入(inject)
  • 这严格来说是由静态分析的类型提示引起的循环
  • 我知道以下导入选项(效果很好):
  • 替换 from [...] import [...]import [...]
  • MainMenu.__init__ 中进行进口离开file_menu.py独自的

  • 最佳答案

    Does the process of "type checking" mean code is not executed?



    对,就是这样。类型检查器从不执行您的代码:相反,它会分析它。类型检查器的实现方式与编译器的实现方式几乎相同,只是减去了“生成字节码/汇编/机器代码”步骤。

    这意味着您的类型检查器比 Python 解释器在运行时拥有更多可用于解决导入周期(或任何类型的周期)的策略,因为它不需要尝试盲目地导入模块。

    例如,mypy 所做的基本上是从逐个模块分析您的代码开始,跟踪正在定义的每个新类/新类型。在此过程中,如果 mypy 看到使用尚未定义的类型的类型提示,请将其替换为占位符类型。

    一旦我们完成了所有模块的检查,检查并查看是否还有任何占位符类型 float 。如果是这样,请尝试使用我们迄今为止收集的类型定义重新分析代码,并尽可能替换任何占位符。我们冲洗并重复,直到没有更多的占位符或者我们已经迭代了太多次。

    在那之后,mypy 假定任何剩余的占位符都是无效类型并报告错误。

    相比之下,Python 解释器没有像这样反复重新分析模块的奢侈。它需要运行它看到的每个模块,并且反复重新运行模块可能会破坏一些用户代码/用户期望。

    类似地,Python 解释器不能随意交换我们分析模块的顺序。相比之下,mypy 理论上可以以任意顺序分析您的模块,而忽略导入的内容——唯一的问题是它的效率非常低,因为我们需要大量迭代才能达到固定点。

    (因此,mypy 使用您的导入作为建议来决定分析模块的顺序。例如,如果模块 A 直接导入模块 B,我们可能想先分析 B。但如果 A 在 if TYPE_CHECKING 后面导入 B,则可能如果可以帮助我们打破循环,可以放宽订购。)

    关于python - mypy如何使用typing.TYPE_CHECKING解决循环导入注解问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61545580/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com