Yur*_*hev 1 python python-import
我是 Python 新手,之前我一直在使用像 Swift 这样的语言,其中导入并不是什么大问题:您只是定义了一个新类,并且可以从程序的另一部分访问它。
我不能在 Python 中使用这种方式,因为这里 import 以另一种方式工作:您不能进行循环导入,其中两个文件相互导入。我知道我因为以错误的方式使用语言而面临这个问题,但我不明白如何避免它。
我的意思是,在大多数情况下,您可以通过将两个类合并到一个文件中来解决这个问题,但感觉不对。另外,我发现了诸如“将您的导入语句移动到文件末尾”之类的建议,但这也不是一个好主意。
如果您愿意,我想了解 Python 的哲学。在决定在一个单独的文件中创建一个类时,我应该如何组织我的项目以及我应该以什么为指导?
您当然可以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导入,它将使模块处于当前的部分构造状态。因此,模块级代码不能被定义如下访问对象中。parentimport parentfrom parent import somethingparentchildimport childparent.pychild的模块级代码运行完毕,控制权将返回到语句parent下方import child,Python 将完成parent.如果child的模块级代码尝试访问parent在import child语句之后定义的对象(因为加载parent时仅部分完成child),则此过程会给您带来麻烦。这个问题的解决是导入parent在模块级child,但内延迟访问对象parent从child以后才child和parent已完成加载。特别是,您可能需要使用,然后从 中的函数或方法代码内部访问,而不是使用from parent import somethinginchild的模块级代码。这是安全的,因为这些函数和方法将直到后运行,并完成运行后,在该点的所有元素import parentparent.somethingchildchildparentparent 模块被正确定义。
这是我的意思的一个例子,使用您在评论中描述的设置。如果您提供有关给您带来问题的代码的更多信息,我可以更密切地对其进行调整。
版本 1(不起作用)
__main__.py:
from user import User
u = User()
Run Code Online (Sandbox Code Playgroud)
用户.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
Run Code Online (Sandbox Code Playgroud)
数据管理器.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
Run Code Online (Sandbox Code Playgroud)
版本 2(将工作)
__main__.py:
from user import User
u = User()
Run Code Online (Sandbox Code Playgroud)
用户.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
Run Code Online (Sandbox Code Playgroud)
数据管理器.py:
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
Run Code Online (Sandbox Code Playgroud)
请注意,在__init__实际实例化类之前,不会解析类方法中的引用。即,该user = user_module.User(data_manager=self)行执行以下操作:“在当前模块中user_module查找名为 的对象;在该对象中查找User属性;构造该类的对象”。重要的是data_manager可以在user早期安全地导入模块(模块已经存在,即使它只是部分构造),但上面的代码实际上不会在user模块内部查找任何内容,直到DataManager对象被实例化,此时user.User将被正确定义。
| 归档时间: |
|
| 查看次数: |
2608 次 |
| 最近记录: |