Python 如何避免循环导入
我是Python新手,之前我一直在使用像Swift这样的语言,导入不是什么大问题:您只是定义一个新类,可以从程序的另一部分访问它 我不能在Python中使用这种方式,因为这里的导入是以另一种方式工作的:不能进行循环导入,两个文件相互导入。我知道我面临这个问题是因为我用错了语言,但我不知道如何避免它 我的意思是,在大多数情况下,您可以通过将两个类合并到一个文件中来解决这个问题,但感觉不太对。此外,我还找到了类似“将导入语句移到文件末尾”的建议,但这也不是一个好主意 如果你愿意的话,我想了解Python的哲学。当我决定在一个单独的文件中创建一个类时,我应该如何组织我的项目以及我应该遵循什么 我不能在Python中使用这种方式,因为这里的导入是以另一种方式工作的:不能进行循环导入,两个文件相互导入 是的,你可以 假设我们在同一工作目录中有两个文件:Python 如何避免循环导入,python,python-import,Python,Python Import,我是Python新手,之前我一直在使用像Swift这样的语言,导入不是什么大问题:您只是定义一个新类,可以从程序的另一部分访问它 我不能在Python中使用这种方式,因为这里的导入是以另一种方式工作的:不能进行循环导入,两个文件相互导入。我知道我面临这个问题是因为我用错了语言,但我不知道如何避免它 我的意思是,在大多数情况下,您可以通过将两个类合并到一个文件中来解决这个问题,但感觉不太对。此外,我还找到了类似“将导入语句移到文件末尾”的建议,但这也不是一个好主意 如果你愿意的话,我想了解Pyth
#file1.py
import file2
x = 22
y = 'spam'
print(x)
print(y)
及
注意当我们导入file1.py时会发生什么
file1.py导入file2.py,file2.py导入file1.py。发生此问题的原因是,您编写Python程序就像编写Swift或Java程序一样。这种方法永远不会奏效:每种语言都是不同的,并且有不同的最佳实践。如果你写的是非Python语言的代码,那么它不仅对其他Python开发人员来说难看且无法理解,而且你正在与这种语言斗争,而不是享受它
就像python开发人员构造代码一样构造代码。将相关类分组到一个模块中。如果有一种罕见的情况,即很难避免导入周期(几乎从未发生过),则在函数或方法中导入有问题的依赖项,而不是全局范围。您当然可以从
父项
导入子项
,从子项
导入父项
。这项工作的关键是child
不要从其模块级代码中深入探究parent
,因为当Python在child
中运行模块级代码时,parent
模块只加载了一部分
以下是从parent
导入child
和从child
导入parent
时发生的情况(假设先加载了parent
):
父级
模块级的代码一直运行,直到到达加载子级
的语句(要么导入子级
,要么从子级导入内容
)。“模块级”是指不在类或函数定义中的语句。在模块级定义的类和函数也将作为模块内的对象创建。但是,函数和类方法本身还不会运行父级
的模块级代码中到达导入子级
语句(或等效语句)时,它将停止运行父级
代码,并开始在子级
中运行模块级代码。如果child
通过import parent
或从parent import something
导入parent
,它将获得当前部分构造状态的parent
模块。因此child
中的模块级代码无法访问在parent.py
中的import child
下面定义的对象child
的模块级代码完成运行,控制将返回到import child
语句下面的parent
,Python将完成运行parent
中的所有模块级代码child
的模块级代码在import child
语句之后试图访问在parent
中定义的对象,则此过程会给您带来麻烦(因为parent
仅在child
加载时部分完成)。解决方案是在child
的模块级导入parent
,但延迟从child
访问parent
中的对象,直到child
和parent
完成加载。特别是,您可能需要使用导入父级
,然后从子级
中的函数或方法代码访问父级
,而不是在子级
的模块级代码中使用从父级导入某物
。这样做是安全的,因为这些函数和方法只有在子模块
和父模块
完成运行后才会运行,此时父模块的所有元素都已正确定义
下面是一个我的意思的例子,使用您在评论中描述的设置。如果您提供更多关于代码的信息,这些代码会给您带来问题,我可以对其进行更紧密的裁剪
第1版(不起作用)
__主要项目:
from user import User
u = User()
from user import User
u = User()
user.py:
from data_manager import DataManager
...
class User:
def __init__(self, data_manager=None):
if data_manager is None:
data_manager = DataManager(user=self)
self.data_manager = data_manager
import data_manager as dm
...
class User:
def __init__(self, data_manager=None):
if data_manager is None:
data_manager = dm.DataManager(user=self)
self.data_manager = data_manager
data_manager.py:
# next line will fail because user.py has been partly loaded
# and user.User doesn't exist yet
from user import User
...
class DataManager:
def __init__(self, user=None):
...
if user is None:
user = User(data_manager=self)
self.user = user
import user as user_module
...
# this defines a class which will eventually create an instance
# of user.User, but it won't try to do that until control returns
# to __main__.py, by which point the `user` and `data_manager`
# modules are fully defined
class DataManager:
def __init__(self, user=None):
...
if user is None:
user = user_module.User(data_manager=self)
self.user = user
第2版(将起作用)
__主要项目:
from user import User
u = User()
from user import User
u = User()
user.py:
from data_manager import DataManager
...
class User:
def __init__(self, data_manager=None):
if data_manager is None:
data_manager = DataManager(user=self)
self.data_manager = data_manager
import data_manager as dm
...
class User:
def __init__(self, data_manager=None):
if data_manager is None:
data_manager = dm.DataManager(user=self)
self.data_manager = data_manager
data_manager.py:
# next line will fail because user.py has been partly loaded
# and user.User doesn't exist yet
from user import User
...
class DataManager:
def __init__(self, user=None):
...
if user is None:
user = User(data_manager=self)
self.user = user
import user as user_module
...
# this defines a class which will eventually create an instance
# of user.User, but it won't try to do that until control returns
# to __main__.py, by which point the `user` and `data_manager`
# modules are fully defined
class DataManager:
def __init__(self, user=None):
...
if user is None:
user = user_module.User(data_manager=self)
self.user = user
请注意,在类的\uuuu init\uuu
方法中的引用在类实际实例化之前不会得到解析。i、 例如,user=user\u module.user(data\u manager=self)
行执行如下操作:“在当前模块中查找名为user\u module
的对象;在该对象中查找user
属性;构造该类的对象”。重要的是,data\u manager
可以在早期安全地导入user
模块(该模块已经存在,即使它只是部分构造的),但是在实例化DataManager
对象之前,上面的代码实际上不会在user
模块内查找任何内容,此时u