Python中的循环依赖

Python中的循环依赖,python,circular-dependency,Python,Circular Dependency,我有两个文件,node.py和path.py,它们分别定义了两个类,node和path 到目前为止,Path的定义引用了节点对象,因此我已经完成了 from node.py import * 在path.py文件中 但是,从今天起,我为节点创建了一个引用路径对象的新方法 我在尝试导入path.py时遇到问题:我尝试了它,当程序运行并调用使用Node的path方法时,出现了一个关于未定义Node的异常 我该怎么办?是一篇用Python解释循环导入的好文章 解决此问题的最简单方法是将路径导入移动到

我有两个文件,
node.py
path.py
,它们分别定义了两个类,
node
path

到目前为止,
Path
的定义引用了
节点
对象,因此我已经完成了

from node.py import *
path.py
文件中

但是,从今天起,我为
节点
创建了一个引用
路径
对象的新方法

我在尝试导入
path.py
时遇到问题:我尝试了它,当程序运行并调用使用
Node
path
方法时,出现了一个关于未定义
Node
的异常

我该怎么办?

是一篇用Python解释循环导入的好文章


解决此问题的最简单方法是将路径导入移动到节点模块的末尾。

另一种方法是仅在函数中导入两个模块中的一个,而在另一个模块中需要导入。当然,如果您只需要在一个或少数功能中使用它,则此功能效果最佳:

# in node.py 
from path import Path
class Node 
    ...

# in path.py
class Path
  def method_needs_node(): 
    from node import Node
    n = Node()
    ...

我更喜欢通过在另一个依赖类的构造函数中声明一个依赖项来打破循环依赖项。在我看来,这使代码保持整洁,并使需要依赖关系的所有方法都可以轻松访问

所以在我的例子中,我有一个CustomerService和一个UserService,它们相互依赖。我打破循环依赖,如下所示:

class UserService:

    def __init__(self):
        # Declared in constructor to avoid circular dependency
        from server.portal.services.admin.customer_service import CustomerService
        self.customer_service = CustomerService()

    def create_user(self, customer_id: int) -> User:
        # Now easy to access the dependency from any method
        customer = self.customer_service.get_by_id(customer_id)

您可能不需要在
node.py
中导入
Path
,以便
Path
node
相互利用

# in __init__.py  (The order of imports should not matter.)
from .node import Node
from .path import Path

# in path.py 
from . import Node
class Path
  ...

  def return_something_pathy(self): 
    ...

# in node.py
class Node
  def __init__(self, path): 
    self.path = path
    ...

  def a_node_method():
    print(self.path.return_something_pathy())
要明确说明
节点
正在使用
路径
,请添加类型提示。从Python 3.7开始,有一个功能支持类型注释中的正向引用,如中所述


是一篇教我这一点的博文。

重复?你想让每个文件都有一个类吗?这就是为什么这很少奏效的原因。同意S·洛特的观点。Python不是Java。你不需要每个文件都有一个类,有几个人说过“你不需要每个文件都有一个类”和大意是“不要试图成为Java”。好吧,但这离题了。类定义可能会变得非常大,将它们捆绑到同一个文件中可能会导致文件非常大,无法读取。在我处理的一个程序中,有8个相互依赖的类,每个类的长度都有几百行,我认为将它们保存在同一个文件中没有好处,将它们分开也有相当大的好处。upvote@sfkleach不够。。如果一个多类文件中的1000+LOC还不足以读取或维护,那么测试文件(人们确实为Python类编写测试,对吗?)将变得更长,甚至更像是维护的噩梦。仅仅因为Python有时会使良好的组织变得困难,并不意味着我们应该放弃可维护的代码。好吧,但问题是,我在该包中还有另外两个模块
tree.py
block.py
,它们需要
node.py
,并且是
path.py
所需要的。那么我应该把它们都放在一个文件里吗?我喜欢每堂课有一个模块。你试过我的建议吗?这可能有用。只需将导入移动到文件的末尾。我建议你阅读这篇文章来理解为什么会发生这种情况。顺便问一下,除了你“喜欢”它之外,还有其他原因让你想要每个模块上一节课吗?我很少看到这种偏好,这是因为它类似于Java。导入Python模块的链接断开了。它可以工作,但我看不到这种通过的可读性代码审查
# in node.py  (Now with type hinting.)
from __future__ import annotations

class Node
  def __init__(self, path: Path): 
    self.path = path
    ...

  def a_node_method():
    print(self.path.return_something_pathy())