Python导入:在“子”中改变变量会影响“父”/其他“子”吗?
假设你有三个模块,分别是 a.py、b.py 和 c.py:
a.py:
v1 = 1
v2 = 2
etc.
b.py:
from a import *
c.py:
from a import *
v1 = 0
那么,c.py 会改变 a.py 和 b.py 中的 v1 吗?如果不会,有什么办法可以做到这一点吗?
3 个回答
是的,你只需要正确地访问它(而且不要使用 import *,那是个坏主意)
c.py:
import a
print a.v1 # prints 1
a.v1 = 0
print a.v1 # prints 0
使用 from ... import *
这种写法主要是为了在交互式环境中方便使用,但在其他情况下最好不要用,因为这样会带来很多麻烦。
实际上,我所在公司的内部风格指南更进一步,建议总是导入整个模块,而不是从模块中导入特定的内容(从包中导入模块是可以的,甚至是推荐的)。因此,在我们的代码中,引用导入的内容时总是使用带有模块名的完整名称,比如 themod.thething
,而不是简单的名称(简单名称总是指内置的、全局的或者局部的内容);这样做让代码更清晰、更易读,也避免了各种微妙的问题。
当然,如果模块名太长,可以在导入时使用 as
来给它起个更短、更方便的别名,这样在导入的模块中使用就更方便了。但对于那些只有一个字母的模块名,就不需要这样做了;-)。
所以,如果你遵循这个指南,总是导入整个模块(而不是里面的内容),那么 c.v1
总是指向和 a.v1
以及 b.v1
一样的东西,无论是获取还是设置:这样就避免了一个潜在的微妙问题!-)
记住《Python之禅》的最后一条(在交互式环境中输入 import this
可以看到所有内容):
Namespaces are one honking great idea -- let's do more of those!
导入整个模块(而不是其中的某些部分)可以保持它作为命名空间的完整性,始终使用带有模块名的完整名称来引用导入模块中的内容也是如此。这真是个好主意:多这样做吧!-)
像这样的语句:
v1 = 0
只能把名字 v1
绑定到对象 0
上。它不能影响其他模块。
如果我用了一些你不太熟悉的术语,我想我可能确实用了,强烈建议你去看看 Fredrik Lundh 的一篇很棒的文章 Python 对象:重置你的思维。