Python:设置属于导入模块命名空间的变量
假设我有一个模块叫做 params.py
,里面声明了一堆变量:
a = 0.2
b = 0.4
...
在使用这个模块的时候,我想用 * 来导入它的命名空间,这样引用起来更方便。但是这样做似乎只能访问到这些参数的值,却不能重新设置它们:
from params import *
def test1():
print(a) #this works: printing out the value of params.a
def test2():
a= 0.5 #doesn't work: does not change the value of params.a
我尝试用 params.a = 0.5
来引用这个变量,但也不行(出现了 NameError,提示 "params" 没有定义)
我的问题是:用这种方式导入的变量,怎么才能设置或重置它的值呢?
2 个回答
1
好吧,我想到的简单解决办法是对同一个模块使用两个导入语句:
from params import *
import params
第一个语句让我可以直接使用变量的值,而不需要加上 "params."
前缀,第二个语句则让我在需要的时候重新绑定这些变量。
params.a = 0.5
我不知道这样做是否符合最佳实践(可能不符合)。不过就我所见,这个方法是有效的。欢迎其他建议。
编辑:这个方法不行,因为变量 a
的值不会反映更新后的值:
print(a) #say it prints 0.2
params.a = 0.5
print(a) # will still print 0.2
print(params.a) #will print 0.5
所以这里的教训是,如果你用 from params import a
导入了变量,那么即使原始值发生了变化,你也只能得到当初导入时的值。也就是说,这是按值导入,而不是按引用导入。
3
在 test2()
函数里把 a = 0.5
赋值,只对这个函数有效,也就是说它是局部的。
你想做的是给模块设置属性。
举个例子:
import params
def test1():
print(params.a)
def test2():
params.a = 0.5
详细信息请查看:Python作用域规则的简要说明
注意: 了解Python几乎所有东西都是某种对象,并且通常都有属性,这一点是很有帮助的。这包括模块、类、类的实例、函数等等。
更新:虽然这样做不太推荐,但这确实能“完全”实现你想要的效果:
foo.py:
from params import * # noqa
def test1():
print(a)
def test2():
global a
a = 0.5
params.py:
a = 1
demo:
$ python -i foo.py
>>> test1()
1
>>> test2()
>>> test1()
0.5
>>>
更新 II: 不过我还要指出,正如我在评论中提到的,这实际上并没有改变 params.a
的引用。请看:
$ python -i foo.py
>>> id(params.a)
140602494749016
>>> id(a)
140602494749016
>>> test1()
1
>>> test2()
>>> test1()
0.5
>>> id(params.a)
140602494749016
>>> id(a)
140602494760472
>>>
总结: 一般来说,请使用这里提供的第一个选项。