我是一个python beginne,目前正在学习python中的导入模块。 所以我的问题是: 假设我目前有三个python文件,分别是module1.py,module2.py和module3.py;
在module1.py中:
def function1():
print('Hello')
在module2.py中,为了在module1.py中使用这些函数:
import module1
#Also, I have some other public functions in this .py file
def function2():
print('Goodbye')
#Use the function in module1.py
if __name__ == '__main__':
module1.function1();
function2();
在module3.py中,我想使用module1.py和module2.py。
中的两个函数import module1
import module2
def function3():
print('Nice yo meet you');
if __name__ == '__main__':
module1.function1()
function3()
module2.function2()
好像很有效。但我的问题主要是关于module3.py。原因是在module3.py中,我导入了module1和module2。但是,module1已经由module2导入。我只是想知道这是一个很好的代码方式吗?这有效吗?我应该这样做吗?或者我应该避免这样做以及为什么?
非常感谢你。我只是一个初学者,所以如果我问愚蠢的问题,请原谅我。谢谢!!
答案 0 :(得分:2)
如果你避免循环导入就没有问题,那就是你永远不会导入一个自己导入当前导入模块的模块。
模块没有看到导入器命名空间,因此导入器代码中的导入不会成为导入模块的全局变量。
此外,模块顶级代码仅在首次导入时运行。
编辑1:
我在这里回答菲利普的评论,因为它更容易。
“如果您避免循环导入将没有问题” - >这是不正确的,python在大多数情况下都是圆形导入。“
你感觉到我的一些误解的事实并没有使那个特定的陈述不正确。这是正确的,这是很好的建议。
(说大部分都没关系看起来有点像说大部分时间都会运行正常......)
我明白你的意思了。我避免这么多,以至于我甚至认为你的第一个例子会马上给出错误(事实并非如此)。你的意思是没有必要避免它,因为大多数时候(实际上给定某些条件)Python会很好用它。我也确信有些情况下,循环进口是最简单的解决方案。如果我们有选择的话,这并不意味着我们应该使用它们。这将促进使用糟糕的架构,其中每个模块都依赖于彼此。
这也意味着编码人员必须了解这些警告。
此链接我在SO中发现here表示对循环导入的一些担忧。
之前的链接有些陈旧,因此较新的Python版本信息可能已过时,但import confusion甚至更旧,仍然是3.6.2。
您提供的示例效果很好,因为相关或初始化模块代码包含在函数中,并且不会在导入时运行。使用if __name__ == "__main__":
保护代码也会在导入时将其从运行中删除。
像这样简单的东西(来自effbot.org的相同例子)将不起作用(记住OP说他是初学者):
# file y.py
import x
x.func1()
# file x.py
import y
def func1():
print('printing from x.func1')
在您的第二条评论中,您说: “这也是不正确的。导入的模块将成为命名空间的一部分”
是。但我没有提及,也没有相反。我只是说导入的模块代码不知道导入代码的命名空间。
为了消除歧义我只是意味着:
# w.py
def funcw():
print(z_var)
# z.py
import w
z_var = 'foo'
w.funcw() # error: z_var undefined in w module namespace
运行z.py
会显示错误。这就是我的意思。
现在进一步,为了获得我们想要的访问权限,我们进行循环......
# w.py
import z # go circular
def funcw():
'''Notice that we gain access not to the z module that imported
us but to the z module we import (yes its the same thing but
carries a different namespace). So the reference we obtain
points to a different object, because it really is in a
different namespace.'''
print(z.z_var, id(z.z_var))
...我们保护一些代码免于运行导入:
# z.py
import w
z_var = ['foo']
if __name__ == '__main__':
print(z_var, id(z_var))
w.funcw()
通过运行z.py
我们确认对象是不同的(它们可以与不可变对象相同,但这是python kerning - 内部优化或实现细节 - 在工作中):
['foo'] 139791984046856
['foo'] 139791984046536
最后,我同意你关于明确进口的第三条评论。
无论如何,我感谢你的评论。实际上,由于它们,我实际上提高了对问题的理解(我们通过避免它来学习很多东西)。