如何制作跨模块变量?

Dan*_*ick 117 python module global

__debug__变量很方便,部分原因是它影响每个模块.如果我想创建另一个以相同方式工作的变量,我该怎么做?

变量(让我们是原始的并称之为'foo')并不一定是真正的全局变量,因为如果我在一个模块中更改foo,它会在其他模块中更新.如果我可以在导入其他模块之前设置foo然后他们会看到相同的值,我会没事的.

jfs*_*jfs 153

如果您需要一个全局跨模块变量,那么简单的全局模块级变量就足够了.

a.py:

var = 1
Run Code Online (Sandbox Code Playgroud)

b.py:

import a
print a.var
import c
print a.var
Run Code Online (Sandbox Code Playgroud)

c.py:

import a
a.var = 2
Run Code Online (Sandbox Code Playgroud)

测试:

$ python b.py
# -> 1 2
Run Code Online (Sandbox Code Playgroud)

真实世界的例子:Django的global_settings.py(虽然在Django应用程序设置中使用导入对象 django.conf.settings).

  • 在现实世界中,您必须对此解决方案保持谨慎.如果程序员使用'from import var'来获取你的'全局'变量,(在c.py中尝试这种变化),他们会在导入时获得变量的副本. (6认同)
  • @sedeh:不.如果a.py也作为脚本运行,那么在其中使用`if __name __ =="__ main __"`guard,以避免在导入时运行意外代码. (4认同)
  • 更好,因为它避免了可能的命名空间冲突 (2认同)
  • @PaulWhipp:**错误**(提示:使用 `id()` 检查身份) (2认同)
  • @pevogam:不,“导入”不会“复制”对象。我敢打赌您已经使用了“from a import var”(“var”现在位于不同的命名空间中)而不是我的答案中的“import a”。(“var”保留在“a”模块命名空间中)。两种情况下对象是相同的,没有副本。相关:[在Python中,为什么函数可以修改调用者感知到的某些参数,而不是其他参数?](http://stackoverflow.com/q/575196/4279) (2认同)

Cur*_*her 110

我不以任何方式,形状或形式认可这种解决方案.但是如果你向__builtin__模块添加一个变量,它就可以像任何其他模块中的全局变量一样被访问__builtin__- 默认情况下都包含它们.

a.py包含

print foo
Run Code Online (Sandbox Code Playgroud)

b.py包含

import __builtin__
__builtin__.foo = 1
import a
Run Code Online (Sandbox Code Playgroud)

结果是打印"1".

编辑:__builtin__模块可用作本地符号__builtins__- 这是其中两个答案之间存在差异的原因.另请注意,__builtin__builtins在python3中重命名为.

  • 首先,它在人们阅读代码时打破了人们的期望."这里使用的'foo'符号是什么?为什么我看不到它的定义?" (29认同)
  • 如果未来版本的Python开始使用您选择作为实际内置的名称,它也容易造成严重破坏. (8认同)
  • 对于与导入模块共享数据库连接之类的事情,这是一个很好的解决方案.作为一个完整性检查,我确保导入的模块断言`hasattr(__ builtin __,'foo")`. (4认同)
  • 有什么理由,你不喜欢这种情况? (2认同)
  • 我建议删除import`__builtin__`并使用`__builtins__` (2认同)
  • 对于读这个答案的人:__DONT!做!这个!__真的,不要. (2认同)
  • @brunodesthuilliers 实际上,在某些情况下这很方便:)例如,在 IPython 笔记本上,我们希望一些内部函数全局公开一些变量,以便我们可以使用它 (2认同)

hay*_*lci 23

定义一个模块(称之为"globalbaz")并在其中定义变量.使用此"伪全局"的所有模块都应导入"globalbaz"模块,并使用"globalbaz.var_name"引用它.

无论更改的位置如何,都可以使用,您可以在导入之前或之后更改变量.导入的模块将使用最新值.(我在玩具示例中对此进行了测试)

为了澄清,globalbaz.py看起来像这样:

var_name = "my_useful_string"
Run Code Online (Sandbox Code Playgroud)


Dav*_*hel 23

我相信在很多情况下它确实有意义,并且它简化了编程,使得一些全局变量在几个(紧密耦合的)模块中是已知的.本着这种精神,我想详细说明一个全局变量模块的想法,这些模块由那些需要引用它们的模块导入.

当只有一个这样的模块时,我将其命名为"g".在其中,我为我打算视为全局的每个变量分配默认值.在使用其中任何一个的每个模块中,我不使用"from g import var",因为这只会产生一个局部变量,该变量仅在导入时从g初始化.我以g.var和"g"的形式创建了大多数引用.作为一个不断提醒我,我正在处理其他模块可能访问的变量.

如果要在模块中的某个函数中频繁使用此类全局变量的值,则该函数可以生成本地副本:var = g.var.但是,重要的是要认识到var的赋值是本地的,并且如果没有在赋值中显式引用g.var,则无法更新全局g.var.

请注意,您还可以使用模块的不同子集共享多个此类全局模块,以使事情更加严格控制.我为我的全局模块使用短名称的原因是为了避免因出现它们而过多地混淆代码.只有一点点经验,它们只有1或2个字符就足够了.

当g尚未在g中定义时,仍然可以对gx进行赋值,然后另一个模块可以访问gx但是,即使解释器允许它,这种方法也不是那么透明,我确实避免它.由于作业的变量名称中存在拼写错误,因此仍有可能在g中意外创建新变量.有时,对dir(g)的检查有助于发现可能由此类事故引起的任何惊喜名称.

  • 这个有趣的观察解决了我的问题:"我不使用"来自g import var",因为这只会产生一个局部变量,只在导入时从g初始化." 假设"from..import"与"import"相同似乎是合理的,但事实并非如此. (6认同)

use*_*430 9

您可以将一个模块的全局变量传递给另一个模块:

在模块A中:

import module_b
my_var=2
module_b.do_something_with_my_globals(globals())
print my_var
Run Code Online (Sandbox Code Playgroud)

在模块B中:

def do_something_with_my_globals(glob): # glob is simply a dict.
    glob["my_var"]=3
Run Code Online (Sandbox Code Playgroud)

  • 方便测试! (2认同)

spi*_*piv 7

全局变量通常是一个坏主意,但您可以通过分配到__builtins__:

__builtins__.foo = 'something'
print foo
Run Code Online (Sandbox Code Playgroud)

此外,模块本身是您可以从任何模块访问的变量.因此,如果您定义一个名为的模块my_globals.py:

# my_globals.py
foo = 'something'
Run Code Online (Sandbox Code Playgroud)

然后你也可以在任何地方使用它:

import my_globals
print my_globals.foo
Run Code Online (Sandbox Code Playgroud)

使用模块而不是修改__builtins__通常是一种更简洁的方法来完成这种全局变量.

  • `__builtins__`是一个CPython的特性,你真的不应该使用它 - 更好地使用`__builtin__`(或Python3中的`builtins`)作为[接受的答案](http://stackoverflow.com/a/142566/321973)节目 (3认同)

int*_*ted 5

您已经可以使用模块级变量执行此操作.无论从哪个模块导入,模块都是相同的.因此,您可以将变量作为模块级变量放在任何有意义的模块中,并将其访问或从其他模块分配给它.最好调用一个函数来设置变量的值,或者使它成为某个单例对象的属性.这样,如果您最终需要在变量更改时运行某些代码,则可以在不破坏模块外部接口的情况下执行此操作.

这通常不是一种很好的方式 - 使用全局变量很少 - 但我认为这是最干净的方法.