我今天感觉特别厚。 考虑
mod1.py
count = 0
def foo ():
global count
count = count + 1
mod2.py
import mod1
from mod1 import foo, count
print("mod1.count = ", mod1.count)
print("count = ", count)
foo()
print("mod1.count = ", mod1.count)
print("count = ", count)
我假设将计数导入 mod2 有效地将其全球化。
> python3 mod2.py
mod1.count = 0
count = 0
mod1.count = 1
count = 0
我显然有一些根本性的误解。 我假设导入本质上会使mod1.count和count别名,但事实并非如此。 我猜这与同时使用"导入"和"从导入"有关。
它们之间的区别可能在于可用性。
import module
允许您使用.
运算符从模块访问方法。
from module import something
允许您使用something
而不使用运算符引用模块.
。 您也可以说它可以让您在全球范围内使用something
。
使用from
方法,您将全局导入something
。这并不意味着module
的something
已经消失了。它只是制作方法的新实例。 因此,当您同时导入module
和something
的实例时,您可以按任何一种方式访问something
(无论是否使用.
运算符(。
我想你已经回答了你自己的问题。它们不是别名,而是两个不同的对象,大概是因为它们存在于不同的命名空间中。您可以通过导入然后print(mod1.count is count)
.如果它们是别名,这将返回True
。
这是由于Python处理变量名称的方式。为了给解释提供一些基础,我用一个列表作为第二个导入的变量来扩展您的示例:
mod1.py
count = 0
lst = [1, 2, 3]
def update_count():
global count
count = count + 1
def update_lst():
lst.append(4)
test.py
import mod1
from mod1 import count, lst, update_count, update_lst
print("mod1.count = ", mod1.count)
print("count = ", count)
print("mod1.lst = ", mod1.lst)
print("lst = ", lst)
update_count()
update_lst()
print('nAfter updates: n')
print("mod1.count = ", mod1.count)
print("count = ", count)
print("mod1.lst = ", mod1.lst)
print("lst = ", lst)
输出:
mod1.count = 0
count = 0
mod1.lst = [1, 2, 3]
lst = [1, 2, 3]
After updates:
mod1.count = 1
count = 0
mod1.lst = [1, 2, 3, 4]
lst = [1, 2, 3, 4]
那么,发生了什么?
导入count
和lst
时,将在脚本的命名空间中创建这些新名称。名称count
是mod1.count
已经引用的整数对象0
的另一个名称,而名称lst
是mod1.lst
已经引用的列表的另一个名称。
当我们执行更新时,列表在模块中更新,但它仍然是同一个对象:mod1.lst
和lst
仍然引用同一个对象。
对于mod1.count
来说,情况就不同了,因为我们在count = count + 1
中使这个名称指的是一个新对象,整数1
。 现在,mod1.count
引用整数对象1
,而主脚本中的count
仍然引用原始0
对象。
所以,这只是正常的Python名称行为。
如果你还没有读过它,我推荐Ned Batchelder关于Python名称和值的经典事实和神话,它很好地解释了名称在Python中是如何工作的。