Python导入:在“子”中改变变量会影响“父”/其他“子”吗?

2 投票
3 回答
590 浏览
提问于 2025-04-15 13:29

假设你有三个模块,分别是 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 个回答

1

是的,你只需要正确地访问它(而且不要使用 import *,那是个坏主意)

c.py:

import a
print a.v1 # prints 1
a.v1 = 0
print a.v1 # prints 0
2

使用 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!

导入整个模块(而不是其中的某些部分)可以保持它作为命名空间的完整性,始终使用带有模块名的完整名称来引用导入模块中的内容也是如此。这真是个好主意:多这样做吧!-)

5

像这样的语句:

v1 = 0

只能把名字 v1 绑定到对象 0 上。它不能影响其他模块。

如果我用了一些你不太熟悉的术语,我想我可能确实用了,强烈建议你去看看 Fredrik Lundh 的一篇很棒的文章 Python 对象:重置你的思维

撰写回答