我有两个文件node.py
和path.py
,它们分别定义了两个类Node
和Path
。
到今天为止,Path
引用Node
对象的定义,因此我做了
from node.py import *
在path.py
文件中。
但是,截至今天,我为Node
引用该Path
对象创建了一个新方法。
尝试导入时遇到问题path.py
:我试过了,当程序运行并调用Path
使用的方法时,出现了一个关于未定义Node
的异常。Node
我该怎么办?
我有两个文件node.py
和path.py
,它们分别定义了两个类Node
和Path
。
到今天为止,Path
引用Node
对象的定义,因此我做了
from node.py import *
在path.py
文件中。
但是,截至今天,我为Node
引用该Path
对象创建了一个新方法。
尝试导入时遇到问题path.py
:我试过了,当程序运行并调用Path
使用的方法时,出现了一个关于未定义Node
的异常。Node
我该怎么办?
Importing Python Modules是一篇很棒的文章,它解释了 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()
...
您可能不需要导入Path
以node.py
供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())
为了清楚地表明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 中的循环导入漏洞,这是一篇很棒的博客文章,它教会了我这一点。
我更喜欢通过在另一个依赖类的构造函数中声明一个依赖项来打破循环依赖项。在我看来,这使代码更整洁,并且可以轻松访问所有需要依赖项的方法。
所以就我而言,我有一个相互依赖的 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)
另一种方法是在同一个模块中定义它们,并延迟定义类型。有点像这样:
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