事情是这样的。
首先,Python真正拥有的唯一全局变量是模块范围内的变量。你不能创造一个真正全局的变量;你所能做的就是在特定的范围内创建一个变量。(如果你在Python解释器中创建了一个变量,然后导入其他模块,你的变量在最外层作用域,因此在你的Python会话中是全局的。)
创建一个模块全局变量所要做的就是赋值给一个名称。
想象一个名为foo.py的文件,它包含这样一行:
X = 1
现在想象你导入它。
import foo
print(foo.X) # prints 1
但是,让我们假设您想要在函数中使用一个模块作用域变量作为全局变量,就像在您的示例中一样。Python的默认值是假设函数变量是本地的。在尝试使用全局变量之前,只需在函数中添加一个全局变量声明。
def initDB(name):
global __DBNAME__ # add this line!
if __DBNAME__ is None: # see notes below; explicit test for None
__DBNAME__ = name
else:
raise RuntimeError("Database name has already been set.")
By the way, for this example, the simple if not __DBNAME__ test is adequate, because any string value other than an empty string will evaluate true, so any actual database name will evaluate true. But for variables that might contain a number value that might be 0, you can't just say if not variablename; in that case, you should explicitly test for None using the is operator. I modified the example to add an explicit None test. The explicit test for None is never wrong, so I default to using it.
Finally, as others have noted on this page, two leading underscores signals to Python that you want the variable to be "private" to the module. If you ever do an import * from mymodule, Python will not import names with two leading underscores into your name space. But if you just do a simple import mymodule and then say dir(mymodule) you will see the "private" variables in the list, and if you explicitly refer to mymodule.__DBNAME__ Python won't care, it will just let you refer to it. The double leading underscores are a major clue to users of your module that you don't want them rebinding that name to some value of their own.
在Python中,不执行import *被认为是最佳实践,而是通过使用mymodule来最小化耦合并最大化显式性。或者通过显式的导入,比如from mymodule import Something。
编辑:如果出于某种原因,你需要在一个没有global关键字的非常旧的Python版本中做类似的事情,有一个简单的解决方案。与其直接设置模块全局变量,不如在模块全局级别使用可变类型,并将值存储在其中。
在你的函数中,全局变量名将是只读的;您将无法重新绑定实际的全局变量名。(如果你在函数中赋值给那个变量名,它只会影响函数中的局部变量名。)但是您可以使用该局部变量名来访问实际的全局对象,并在其中存储数据。
你可以使用列表,但你的代码会很难看:
__DBNAME__ = [None] # use length-1 list as a mutable
# later, in code:
if __DBNAME__[0] is None:
__DBNAME__[0] = name
字典比较好。但最方便的是类实例,你可以只使用一个平凡的类:
class Box:
pass
__m = Box() # m will contain all module-level values
__m.dbname = None # database name global in module
# later, in code:
if __m.dbname is None:
__m.dbname = name
(实际上不需要将数据库名称变量大写。)
我喜欢只使用__m的语法糖。dbname而不是__m[" dbname "];在我看来,这似乎是最方便的解决办法。但是dict溶液也可以工作。
使用dict,您可以使用任何可哈希值作为键,但当您满意于有效标识符的名称时,您可以使用上面的Box之类的普通类。