python中的循环和嵌套导入

本杰明

我现在确实有些头疼,试图找出如何正确导入东西的方法。我的应用程序结构如下:

main.py
util_functions.py
widgets/
 - __init__.py
 - chooser.py
 - controller.py

我将始终从根目录运行我的应用程序,因此我的大多数导入操作都是这样的

from util_functions import *
from widgets.chooser import *
from widgets.controller import *
# ...

我的widgets/__init__.py设置是这样的:

from widgets.chooser import Chooser
from widgets.controller import MainPanel, Switch, Lever

__all__ = [
  'Chooser', 'MainPanel', 'Switch', 'Lever',
]

一切正常,除了widgets/controller.py变得很冗长,我希望将它分割成多个文件:

main.py
util_functions.py
widgets/
 - __init__.py
 - chooser.py
 - controller/
    - __init__.py
    - mainpanel.py
    - switch.py
    - lever.py

问题之一是SwitchandLever类具有静态成员,每个类都需要访问其他成员。将导入与from ___ import ___创建循环导入语法一起使用因此,当我尝试运行重构的应用程序时,一切都在导入时中断了。

我的问题是:如何修复导入,以便拥有良好的项目结构?我无法删除的静态依赖SwitchLever互相。

阿巴内特

官方的Python常见问题解答中涵盖了这一点,我如何拥有相互导入的模块

正如常见问题解答所表明的那样,没有神奇的方法可以解决问题。常见问题解答中描述的选项(比常见问题解答中的详细信息更多):

  • 除了用常量或内建函数初始化的类,函数和变量外,切勿在顶层放置任何东西,也不要放任何from spam import东西,然后通常不会出现循环导入问题。简洁明了,但在某些情况下您可能无法遵循这些规则。
  • 重构模块以将导入移动到模块的中间,其中每个模块定义在导入另一个模块之前需要导出的内容。这可能意味着将类分为两部分,一个可以在行上方的“接口”类,以及一个在行下方的“实现”子类。
  • 以类似的方式重构模块,但是将“导出”代码(带有“接口”类)移动到单独的模块中,而不是将它们移动到导入上方。然后,每个实现模块都可以导入所有接口模块。这具有与上一个相同的效果,其优点是您的代码是惯用的,并且人和自动工具都希望将代码导入模块的顶部,因此可读性更高,但缺点是模块更多。

如常见问题解答所述,“这些解决方案不是互斥的。” 特别是,您可以尝试将尽可能多的顶级代码移入函数主体,用合理的替换尽可能多的from spam import …语句import spam……然后,如果您仍然有循环依赖项,请通过重构为上述无导入导出代码来解决它们生产线或单独的模块中。


不用考虑一般性,让我们看看您的特定问题。

您的switch.Switchlever.Lever类具有“静态成员,每个类都需要访问其他成员”。我假设您是说它们具有使用其他类的类属性或类或静态方法初始化的类属性?


在第一个解决方案之后,您可以进行更改,以便在导入时间后初始化这些值。假设您的代码如下所示:

class Lever:
    switch_stuff = Switch.do_stuff()
    # ...

您可以将其更改为:

class Lever:
    @classmethod
    def init_class(cls):
        cls.switch_stuff = Switch.do_stuff()

现在,在之后的__init__.py,:

from lever import Lever
from switch import Switch

…您添加:

Lever.init_class()
Switch.init_class()

这就是诀窍:通过使初始化显式并选择一个显式顺序来解决模棱两可的初始化顺序。


或者,按照第二个或第三个解决方案,您可以将Lever拆分为LeverLeverImpl然后你做到这一点(无论是作为独立的lever.pyleverimpl.py文件,或作为一个文件在中间进口):

class Lever:
    @classmethod
    def get_switch_stuff(cls):
        return cls.switch_stuff

from switch import Swift

class LeverImpl(Lever):
    switch_stuff = Switch.do_stuff()

现在,您不需要任何init_class方法。当然,您确实需要将属性更改为方法,但是,如果您不喜欢这样做,则可以通过一些工作将其更改为“类@property”(通过编写自定义描述符或使用@propertyin元类)。


请注意,您实际上不需要修复两个类来解决循环问题,只需修复一个即可。从理论上讲,修复这两种方法比较干净,但是在实践中,如果修复起来很丑陋,则只修复不那么丑陋的修复程序,而将依赖项放在相反的方向可能会更好。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

python中的循环和嵌套导入

来自分类Dev

在python中循环导入

来自分类Dev

Python中的While循环和Fibonacci(无需导入或使用“ fib”)

来自分类Dev

在python和嵌套列表中的for循环内追加

来自分类Dev

列表推导中的嵌套循环和条件检查(python)

来自分类Dev

嵌套循环矩阵计算中的Python和Matlab差异

来自分类Dev

Python 中的数据分析(Dataframe 和嵌套循环)

来自分类Dev

在 Python 中循环导入字典

来自分类Dev

退出Python中的嵌套循环

来自分类Dev

Python中的单行嵌套For循环

来自分类Dev

在python中组合嵌套的for循环

来自分类Dev

在python中使用for循环和嵌套列表

来自分类Dev

Python,嵌套循环,匹配和性能

来自分类Dev

在python中使用for循环和嵌套列表

来自分类Dev

Python 文件迭代和嵌套 for 循环

来自分类Dev

JMeter中的嵌套循环和终止条件

来自分类Dev

gnuplot和postscript终端中的嵌套循环

来自分类Dev

C ++中的嵌套循环和矩阵

来自分类Dev

优化javascript中的嵌套for循环和if语句

来自分类Dev

使用zip()函数和Python嵌套嵌套循环的问题

来自分类Dev

嵌套列表和python中的for循环程序给了我疯狂的结果

来自分类Dev

编辑:如何创建“嵌套循环”,将项目返回到Python和Scrapy中的原始列表

来自分类Dev

使用嵌套的 for 循环和范围在 Python 3 中打印所需的显示

来自分类Dev

在python中并行嵌套此for循环

来自分类Dev

在Python 2中嵌套while循环

来自分类Dev

如何打破Python中的嵌套循环?

来自分类Dev

嵌套在python中的for循环中

来自分类Dev

Python中嵌套for循环的矢量化

来自分类Dev

嵌套if循环未在python中触发

Related 相关文章

热门标签

归档