[英]Circular dependency in Python
我有兩個文件, node.py
和path.py
,它們分別定義了兩個類, Node
和Path
。
直到今天, Path
的定義引用了Node
對象,因此我已經完成了
from node.py import *
在path.py
文件中。
但是,截至今天,我為Node
創建了一個引用Path
對象的新方法。
我在嘗試導入path.py
時遇到了問題:我試過了,當程序運行並調用使用Node
的Path
方法時,出現了一個關於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()
...
我更喜歡通過在另一個依賴類的構造函數中聲明一個依賴來打破循環依賴。 在我看來,這使代碼更整潔,並且可以輕松訪問需要依賴項的所有方法。
所以在我的情況下,我有一個 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())
為了明確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 中的圓形導入漏洞中挖掘出來,這是一篇很棒的博客文章,它教會了我這一點。
另一種方法是在同一個模塊中定義它們,並延遲定義類型。 有點像這樣:
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.