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

2025-01-03 08:41:00
admin
原创
102
摘要:问题描述:我知道 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大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1579  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1355  
  信创产品在政府采购中的占比分析随着信息技术的飞速发展以及国家对信息安全重视程度的不断提高,信创产业应运而生并迅速崛起。信创,即信息技术应用创新,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,保障国家信息安全。政府采购作为推动信创产业发展的重要力量,其对信创产品的采购占比情况备受关注。这不仅关系到信创产业的发展前...
信创和国产化的区别   8  
  信创,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,摆脱对国外技术的依赖。近年来,国货国用信创发展势头迅猛,在诸多领域取得了显著成果。这一发展趋势对科技创新产生了深远的推动作用,不仅提升了我国在信息技术领域的自主创新能力,还为经济社会的数字化转型提供了坚实支撑。信创推动核心技术突破信创产业的发展促使企业和科研...
信创工作   9  
  信创技术,即信息技术应用创新产业,旨在实现信息技术领域的自主可控与安全可靠。近年来,信创技术发展迅猛,对中小企业产生了深远的影响,带来了诸多不可忽视的价值。在数字化转型的浪潮中,中小企业面临着激烈的市场竞争和复杂多变的环境,信创技术的出现为它们提供了新的发展机遇和支撑。信创技术对中小企业的影响技术架构变革信创技术促使中...
信创国产化   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用