Python中导入的类函数中的全局变量
我正试图将代码分散到不同的文件中以提高可读性,而导入的文件中引用了未定义的全局名称,这给我带来了麻烦。有没有比在调用时故意将所有必需的值传递给函数更好的解决方案 我当前的代码如下所示:Python中导入的类函数中的全局变量,python,python-2.7,global-variables,Python,Python 2.7,Global Variables,我正试图将代码分散到不同的文件中以提高可读性,而导入的文件中引用了未定义的全局名称,这给我带来了麻烦。有没有比在调用时故意将所有必需的值传递给函数更好的解决方案 我当前的代码如下所示: #foo.py import bar def main(): a = 1 b = bar.Bar() while True: a += 1 b.incr() print a print b.c if __name__ =
#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
def main():
b = new bar.Bar()
while True:
a += 1
b.incr(a)
print a
print b.c
def incr(self,a):
c += a
-
它给了我名称错误:未定义全局名称“a”。我是否需要像这样重写main():
#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
def main():
b = new bar.Bar()
while True:
a += 1
b.incr(a)
print a
print b.c
def incr(self,a):
c += a
然后像这样重写incr():
#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
def main():
b = new bar.Bar()
while True:
a += 1
b.incr(a)
print a
print b.c
def incr(self,a):
c += a
还是有更好的办法
为了记录在案,上面的代码被大量抽象。实际代码涉及大量类和函数,它们传递多种类型的变量,包括一些大型字典
提前谢谢 如果
a
是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
如果需要,您可以导入foo
,然后访问foo.a
。(在这种情况下,循环依赖关系不应该是一个问题,如果uuu name uuu='uuu main uuu'
不会执行两次,或者您可以假设导入了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'))
等内容。因为全局变量通常不是一个好主意,将变量从一个函数传递到另一个函数是更好的选择。感谢@PurityLake和MartijnPieters——关于性能,这不是问题吗?在函数之间传递大量变量是否有一个好的解决方案?把它们都放在一本字典里,或者一本字典的字典里,也许?访问本地人比访问全球人要快,而全球人的字典通常要大得多,使事情变得更糟。所以这可能不是问题;这可能是一种进步。无论如何,性能在这里也不太可能相关。但如果有问题,请将其作为栏
实例上的对象属性。并使用\uuuuuuu\uuuuuu
而不是实例字典。或者将条
移动到Cython中。或者……对象的教科书用法是将数据与函数相关联。如果您有长期存在的数据,这些数据定期被一组函数使用/修改,那么这就是对象的用途。如果您发现您经常需要从一个对象到另一个对象的一些数据,那么您可能需要继承、组合或重新设计您的代码。@yoel:将config
字典传递到每个对象的\uuuu init\uuuu
,这样main就可以更改config['gravity']=2
,并且Rock
可以检查self.config[“重力”]
并找到新值?或者您可以将配置作为类实例而不是dict,因此它是self.config.gravity
。其中一个有问题吗?谢谢-没有。假设a
不仅被条使用,而且被垃圾邮件、鸡蛋和吐司使用。然后共享一个c所有需要使用数据的类之间的配置对象…谢谢-只是为了确保我理解:如果configs['gravity']
等于1,我说configs['gravity']=2
,它删除了旧的重力'
,并创建了一个新的重力'
?因此,当以前创建的对象去查找它时,它只会找到新的值?@yoel:是的,你已经找到了。当你配置['gravity']=2
时,任何在此之后进行配置['gravity']
的人或foo['gravity']
如果foo
是对与configs
相同的词典的引用,将看到2
。