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