Ram*_*hum 72 python dependencies circular-dependency python-import
假设我有以下目录结构:
a\
__init__.py
b\
__init__.py
c\
__init__.py
c_file.py
d\
__init__.py
d_file.py
Run Code Online (Sandbox Code Playgroud)
在a包中__init__.py,c导入包.但是c_file.py进口a.b.d.
程序失败,说尝试导入b时不存在.(它确实不存在,因为我们正在进口它.)c_file.pya.b.d
如何解决这个问题呢?
Dir*_*irk 152
您可以推迟导入,例如a/__init__.py:
def my_function():
from a.b.c import Blah
return Blah()
Run Code Online (Sandbox Code Playgroud)
也就是说,将导入推迟到真正需要之前.但是,我也会仔细查看我的包定义/用法,因为像指出的那样循环依赖可能表示设计问题.
ang*_*son 61
如果一个取决于c和c取决于a,那么它们实际上不是同一个单位吗?
你应该仔细研究为什么你将a和c分成两个包,因为要么你有一些代码你应该拆分成另一个包(使它们都依赖于那个新的包,而不是彼此),或者你应该合并它们成一个包.
zac*_*san 26
我想知道这几次(通常在处理需要彼此了解的模型时).简单的解决方案就是导入整个模块,然后引用您需要的东西.
所以不要这样做
from models import Student
Run Code Online (Sandbox Code Playgroud)
在一个,和
from models import Classroom
Run Code Online (Sandbox Code Playgroud)
在另一方面,就这样做
import models
Run Code Online (Sandbox Code Playgroud)
在其中一个,然后调用models.Classroom当你需要它.
使用类型提示,有更多机会创建循环导入。幸运的是,有一个使用特殊常量的解决方案:typing.TYPE_CHECKING.
以下示例定义了一个Vertex类和一个Edge类。一条边由两个顶点定义,一个顶点维护它所属的相邻边的列表。
class Vertex:
def __init__(self, label):
self.label = label
self.adjacency_list = []
Run Code Online (Sandbox Code Playgroud)
class Edge:
def __init__(self, v1, v2):
self.v1 = v1
self.v2 = v2
Run Code Online (Sandbox Code Playgroud)
导入错误:无法从部分初始化的模块“边缘”导入名称“边缘”(很可能是由于循环导入)
from typing import List
from edge import Edge
class Vertex:
def __init__(self, label: str):
self.label = label
self.adjacency_list: List[Edge] = []
Run Code Online (Sandbox Code Playgroud)
from vertex import Vertex
class Edge:
def __init__(self, v1: Vertex, v2: Vertex):
self.v1 = v1
self.v2 = v2
Run Code Online (Sandbox Code Playgroud)
from typing import List, TYPE_CHECKING
if TYPE_CHECKING:
from edge import Edge
class Vertex:
def __init__(self, label: str):
self.label = label
self.adjacency_list: List['Edge'] = []
Run Code Online (Sandbox Code Playgroud)
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from vertex import Vertex
class Edge:
def __init__(self, v1: 'Vertex', v2: 'Vertex'):
self.v1 = v1
self.v2 = v2
Run Code Online (Sandbox Code Playgroud)
在 Python 3.10 之前的版本中,有条件导入的类型必须用引号括起来,使它们成为“前向引用”,从而将它们隐藏在解释器运行时之外。
在 Python 3.7、3.8 和 3.9 中,解决方法是使用以下特殊导入。
from __future__ import annotations
Run Code Online (Sandbox Code Playgroud)
这允许使用不带引号的类型提示与条件导入相结合。
在 Python 3.10 中,将不再在定义时评估函数和变量注释。相反,字符串形式将保留在相应的注释字典中。静态类型检查器在行为上没有区别,而在运行时使用注释的工具将不得不执行延迟评估。
字符串形式是在编译步骤期间从 AST 获得的,这意味着字符串形式可能不会保留源的确切格式。注意:如果一个注解已经是一个字符串文字,它仍然会被包裹在一个字符串中。
| 归档时间: |
|
| 查看次数: |
63834 次 |
| 最近记录: |