如何避免 Python 中的循环导入?[重复]

2025-01-03 08:41:00
admin
原创
136
摘要:问题描述:我知道 Python 中的循环导入问题之前已经出现过很多次,我也读过这些讨论。这些讨论中反复出现的评论是,循环导入是糟糕设计的标志,应该重新组织代码以避免循环导入。有人能告诉我在这种情况下如何避免循环导入吗?:我有两个类,我希望每个类都有一个构造函数(方法),它接受另一个类的实例并返回该类的实例。更...

问题描述:

我知道 Python 中的循环导入问题之前已经出现过很多次,我也读过这些讨论。这些讨论中反复出现的评论是,循环导入是糟糕设计的标志,应该重新组织代码以避免循环导入。

有人能告诉我在这种情况下如何避免循环导入吗?:我有两个类,我希望每个类都有一个构造函数(方法),它接受另一个类的实例并返回该类的实例。

更具体地说,一个类是可变的,另一个是不可变的。不可变类用于哈希、比较等。可变类也用于执行操作。这类似于集合和冻结集或列表和元组。

我可以将两个类定义放在同一个模块中。还有其他建议吗?

一个玩具示例是类 A,它有一个属性,即列表;类 B,它有一个属性,即元组。然后类 A 有一个方法,它接受类 B 的一个实例并返回类 A 的一个实例(通过将元组转换为列表);同样,类 B 有一个方法,它接受类 A 的一个实例并返回类 B 的一个实例(通过将列表转换为元组)。


解决方案 1:

考虑以下示例 Python 包,其中a.pyb.py相互依赖:

/package
    __init__.py
    a.py
    b.py

循环进口问题的类型

循环导入依赖项通常分为两类,具体取决于您要导入的内容以及在每个模块内使用它的位置。(以及您使用的是 Python 2 还是 3)。

  1. 循环导入模块时出错

在某些情况下,即使您没有引用导入模块中的任何内容,仅导入具有循环导入依赖项的模块也会导致错误。

在 Python 中有几种标准方法来导入模块

import package.a           # (1) Absolute import
import package.a as a_mod  # (2) Absolute import bound to different name
from package import a      # (3) Alternate absolute import
import a                   # (4) Implicit relative import (deprecated, python 2 only)
from . import a            # (5) Explicit relative import

不幸的是,当您有循环依赖项时,只有第 1 和第 4 个选项实际上有效(其余选项都引发ImportError
AttributeError)。一般来说,您不应该使用第 4 种语法,因为它只在 python2 中有效,并且有与其他第三方模块冲突的风险。所以实际上,只有第一种语法可以保证有效。

编辑:ImportErrorAttributeError问题仅出现在 Python 2 中。在 Python 3 中,导入机制已被重写,所有这些导入语句(4 个除外)都可以工作,即使存在循环依赖关系。虽然本节中的解决方案可能有助于重构 Python 3 代码,但它们主要针对使用 Python 2 的人。

绝对导入

只需使用上面的第一个导入语法。这种方法的缺点是,对于大型包,导入名称可能会变得非常长

a.py

import package.b

b.py

import package.a

推迟导入

我已经看到很多软件包中使用了这种方法,但是它对我来说仍然感觉很不方便,并且我不喜欢不能查看模块的顶部并查看其所有依赖项,我还必须搜索所有函数。

a.py

def func():
    from package import b

b.py

def func():
    from package import a

将所有导入的内容放在中央模块中

这种方法也行得通,但存在与第一种方法相同的问题,即所有包和子模块调用都变得非常长。这​​种方法也有两个主要缺陷——它强制导入所有子模块,即使您只使用一个或两个子模块,您仍然无法查看任何子模块并在顶部快速查看它们的依赖关系,您必须仔细筛选函数。

__init__.py

from . import a
from . import b

a.py

import package

def func():
    package.b.some_object()

b.py

import package

def func():
    package.a.some_object()
  1. 使用具有循环依赖关系的导入对象时出错

现在,虽然您可以导入具有循环导入依赖关系的模块,但您无法导入模块中定义的任何对象,也无法在导入模块的顶层的任何位置引用该导入模块。但是,您可以在导入时未运行的函数和代码块中使用导入的模块。

例如,这将有效:

包/a.py

import package.b

def func_a():
    return "a"

包/b.py

import package.a

def func_b():
    # Notice how package.a is only referenced *inside* a function
    # and not the top level of the module.
    return package.a.func_a() + "b"

但这是行不通的

包/a.py

import package.b

class A(object):
    pass

包/b.py

import package.a

# package.a is referenced at the top level of the module
class B(package.a.A):
    pass

你会得到一个例外

AttributeError:模块“package”没有属性“a”

通常,在大多数有效的循环依赖情况下,可以重构或重新组织代码以防止这些错误并在代码块内移动模块引用。

解决方案 2:

仅导入模块,不从模块导入:

考虑a.py

import b

class A:
    def bar(self):
        return b.B()

b.py

import a

class B:
    def bar(self):
        return a.A()

这工作得很好。

解决方案 3:

我们结合了绝对导入和函数,以便更好地阅读并缩短访问字符串。

  • 优点:与纯绝对导入相比,访问字符串更短

  • 缺点:由于额外的函数调用,开销稍大

主/子/a.py

import main.sub.b
b_mod = lambda: main.sub.b

class A():
    def __init__(self):
        print('in class "A":', b_mod().B.__name__)

主要/子/b.py

import main.sub.a
a_mod = lambda: main.sub.a

class B():
    def __init__(self):
        print('in class "B":', a_mod().A.__name__)
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3892  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2717  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   52  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   54  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   49  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用