我是Python的新手,之前我一直在使用像Swift这样的语言,导入并不是什么大不了的事:你只是定义一个新类,并且可以从另一个部分访问它。你的计划。
我无法在Python中使用这种方式,因为此处的导入工作方式是另一种方式:您无法进行循环导入,其中两个文件相互导入。我知道我因为错误地使用语言而面临这个问题,但我不明白如何避免这种情况。
我的意思是,在大多数情况下,你可以通过将两个类组合成一个文件来解决这个问题,但它感觉不对。此外,我已经找到了诸如" 将您的import语句移动到文件末尾的建议"但它也不是一个好主意。
如果愿意,我想了解Python的理念。在决定在单独的文件中创建课程时,我应该如何组织我的项目以及我应该引导什么?
答案 0 :(得分:0)
您当然可以从child
和parent
parent
导出child
。实现这项工作的关键是child
不要从模块级代码中深入探讨parent
,因为parent
模块仅在Python运行时被部分加载child
中的模块级代码。
以下从child
parent
和parent
child
导入parent
时会发生什么情况(假设首先加载parent
):
child
的代码会一直运行,直到它到达加载import child
(from child import something
或import child
)的语句。通过"模块级别",我的意思是不在类或函数定义中的语句。在模块级别定义的类和函数也将作为模块中的对象创建。但是,函数和类方法本身不会运行。parent
模块级代码中的parent
语句(或等效语句)时,它将停止运行child
代码并开始运行模块child
中的级别代码。如果parent
通过import parent
或from parent import something
导入parent
,则会使child
模块处于当前的部分构建状态。因此,import child
中的模块级代码无法访问parent.py
中child
下面定义的对象。parent
的模块级代码完成运行,控件将返回import child
语句下方的parent
,Python将完成所有模块级别的运行child
中的代码。如果parent
的模块级代码尝试访问import child
语句之后parent
中定义的对象,则此过程会给您带来麻烦(自{{1仅child
加载时才会部分完成。解决方法是在parent
的模块级别导入child
,但是将parent
中的对象从child
推迟到child
和{{1}之后已完成加载。特别是,您可能需要使用parent
,然后从内部函数或方法中访问from parent import something
,而不是在child
的模块级代码中使用import parent
parent.something
中的代码。这样做是安全的,因为这些函数和方法在child
和child
完成运行之后才会运行,此时parent
模块的所有元素都被正确定义
这是我的意思的一个例子,使用您在评论中描述的设置。如果你提供有关给你问题的代码的更多信息,我可以更仔细地定制它。
版本1(赢了工作)
。__主__ PY:
parent
user.py:
from user import User
u = User()
data_manager.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
版本2(可以使用)
。__主__ 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
user.py:
from user import User
u = User()
data_manager.py:
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
请注意您班级中的参考资料'在实际实例化类之前,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
方法无法解决。即,__init__
行的行为如下:"在当前模块中查找名为user = user_module.User(data_manager=self)
的对象;在该对象中查找user_module
属性;构建该类的对象"。重要的是User
可以在早期安全地导入data_manager
模块(模块已经存在,即使它只是部分构建),但上面的代码实际上并没有找到任何东西在user
模块内部,直到user
对象被实例化,到时DataManager
将被正确定义。
答案 1 :(得分:-1)
我不能以这种方式使用Python,因为这里的导入工作方式是另一种方式:你不能进行循环导入,其中两个文件相互导入。
是的,你可以!
假设我们在同一个工作目录中有两个文件:
#file1.py
import file2
x = 22
y = 'spam'
print(x)
print(y)
和
#file2.py
import file1
print("file1")
请注意我们导入 file1.py
时会发生什么>>> import file1
file1
22
spam
file1.py 导入 file2.py 和 file2.py 导入 file1.py 。
答案 2 :(得分:-2)
发生此问题是因为您正在编写Python程序,就像编写Swift或Java程序一样。这种方法从来都不行:每种语言都不同,并且有不同的最佳实践。如果你编写unpythonic代码,不仅它看起来很丑陋而且对其他Python开发人员来说难以理解,那么你就会挣扎于语言而不是享受它。
只需像python开发人员那样构建代码。在一个模块中将相关类分组。如果罕见的情况是难以避免导入周期(几乎从未发生过),请在函数或方法中导入违规依赖,而不是全局范围。