Python中导入类函数中的全局变量
我正在尝试把我的代码分散到不同的文件中,以提高可读性,但在导入的文件中遇到了未定义的全局变量的问题。有没有比在调用函数时故意传递所有必要值更好的解决方案?
我现在的代码是这样的:
#foo.py
import bar
def main():
a = 1
b = bar.Bar()
while True:
a += 1
b.incr()
print a
print b.c
if __name__ == '__main__':
main()
#END foo.py
-
#bar.py
class Bar:
def __init__(self):
self.c = 0
def incr(self):
self.c += a
#END bar.py
这让我遇到了NameError错误:全局变量'a'未定义。我需要像这样重写main()吗:
def main():
b = new bar.Bar()
while True:
a += 1
b.incr(a)
print a
print b.c
并且像这样重写incr()吗:
def incr(self,a):
c += a
还是说有更好的方法?
顺便说一下,上面的代码是高度抽象的。实际代码涉及很多类和函数,传递了许多不同类型的变量,包括一些大型字典。
提前谢谢你们!
2 个回答
如果 a
是 Bar
的一个特征或设置,那么它应该是 Bar
的一个实例属性或类属性。
class Bar(object):
class_step = 1
def __init__(self, inst_step):
self.inst_step = inst_step
self.c = 0
self.step_mode = 'class'
def inc(self):
self.c += Bar.class_step if self.step_mode == 'class' else self.inst_step
如果你只是想知道为什么它不工作:
首先,main
函数并没有设置一个全局的a
,而是一个局部的。如果你想让它成为全局的,你需要明确说明:
def main():
global a
a = 1
# ...
但是这并不能解决问题,因为在Python中“全局”是针对每个模块的。换句话说,这只是创建了一个foo.a
,而你在bar.Bar
中的代码会寻找bar.a
,但这个并不存在。
如果你想的话,可以import foo
,然后访问foo.a
。(在这种情况下,循环依赖应该不是问题,if __name__ == '__main__'
也不会被执行两次。)或者你可以假设foo
已经被导入,然后使用sys.modules['foo'].a
。或者你可以从foo
中将a
注入到bar
的字典里。还有很多其他的技巧。但这些都是不太好的做法。
如果你无法让全局变量工作,正确的做法几乎总是不要使用全局变量。(事实上,即使你可以让全局变量工作,通常这也是正确的选择。)
那么,怎么做呢?在不知道更多细节的情况下,很难猜测a
应该作为一个明确的模块全局变量、类属性、实例属性、incr
的参数等等。但找出哪一个最符合a
所代表的意义,然后去做。
在评论中,你提到你有一堆这样的配置变量。如果你把它们都放在一个dict
里,并把这个dict
传给每个对象的构造函数,这样会简单很多。
更重要的是,dict
是一个可变对象的引用。复制它只是创建了对同一个对象的另一个引用。
main.py:
def main():
configs = {}
configs['gravity'] = 1.0
rock = rps.Rock(configs)
rock.do_stuff()
configs['gravity'] = 2.1
rock.do_stuff()
if __name__ == '__main__':
main()
rps.py:
class Rock(object):
def __init__(self, configs):
self.configs = configs
def do_stuff(self):
print('Falling with gravity {}.'.format(self.configs['gravity']))
当你运行这个时,它会打印出类似这样的内容:
Falling with gravity 1.0.
Falling with gravity 2.1.
你并没有修改configs['gravity']
的值(这是一个不可变的浮点数;你不能修改它),但你确实用一个不同的值替换了它(因为configs
是一个可变的dict
;你可以随意修改它)。如果身份不明确,你可以尝试在不同的地方打印出id(self.configs)
、id(self.configs['gravity'])
等信息。