82

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

到今天为止,Path引用Node对象的定义,因此我做了

from node.py import *

path.py文件中。

但是,截至今天,我为Node引用该Path对象创建了一个新方法。

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

我该怎么办?

4

5 回答 5

121

Importing Python Modules是一篇很棒的文章,它解释了 Python 中的循环导入。

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

于 2009-05-21T20:11:55.547 回答
30

另一种方法是仅在另一个需要它的功能中导入两个模块中的一个。当然,如果您只在一个或少数几个函数中需要它,这会最有效:

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

# in path.py
class Path
  def method_needs_node(): 
    from node import Node
    n = Node()
    ...
于 2016-06-14T13:05:35.567 回答
5

您可能不需要导入Pathnode.pyPath彼此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())

为了清楚地表明Node正在使用Path,添加类型提示。从 Python 3.7 开始有一个功能可以支持类型注释中的前向引用,如PEP 563中所述。

# 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())

我遇到了另一个解决方案,可以让您摆脱 Python 中的循环导入漏洞,这是一篇很棒的博客文章,它教会了我这一点。

于 2019-11-04T04:46:54.707 回答
4

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

所以就我而言,我有一个相互依赖的 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)
于 2019-02-27T15:42:07.803 回答
0

另一种方法是在同一个模块中定义它们,并延迟定义类型。有点像这样:

class Node:
   _path_type: type = None
   
   def method_needs_path(self):
       p = self._path_type()
       ...


class Path:
    def method_needs_node(self):
       n = Node()

Node._path_type = Path

对此保持对称可能会更好:

class Node:
   _path_type: type = None
   
   def method_needs_path(self):
       p = self._path_type()
       ...


class Path:
    _node_type: type = None

    def method_needs_node(self):
       n = Node()

Node._path_type = Path
Path._node_type = Node

这也可以在多个模块中完成:

# in node.py
class Node:
   _path_type: type = None
   
   def method_needs_path(self):
       p = self._path_type()
       ...

# in path.py
from .node import Node

class Path:
    _node_type: type = None

    def method_needs_node(self):
       n = self._node_type()

Node._path_type = Path
Path._node_type = Node

# in __init__.py (note that order is important now)
from .node import Node
from .path import Path
于 2021-10-27T09:15:32.183 回答