在Python中使用"global"关键字

nik*_*nik 279 python global-variables

我从阅读文档中了解到,Python有一个单独的函数命名空间,如果我想在该函数中使用全局变量,我需要使用global.

我正在使用Python 2.7,我尝试了这个小测试

>>> sub = ['0', '0', '0', '0']
>>> def getJoin():
...     return '.'.join(sub)
...
>>> getJoin()
'0.0.0.0'
Run Code Online (Sandbox Code Playgroud)

即使没有,事情似乎也很好global.我能够毫无问题地访问全局变量.

我错过了什么吗?另外,以下是来自Python文档:

全局语句中列出的名称不能定义为形式参数,也不能定义为for循环控制目标,类定义,函数定义或import语句.

虽然形式参数和类定义对我有意义,但我无法理解for循环控制目标和函数定义的限制.

uno*_*ode 356

该关键字global仅对在本地上下文中更改或创建全局变量很有用,尽管创建全局变量很少被认为是一个很好的解决方案.

def bob():
    me = "locally defined"    # Defined only in local context
    print me

bob()
print me     # Asking for a global variable
Run Code Online (Sandbox Code Playgroud)

以上将给你:

locally defined
Traceback (most recent call last):
  File "file.py", line 9, in <module>
    print me
NameError: name 'me' is not defined
Run Code Online (Sandbox Code Playgroud)

如果使用该global语句,变量将在函数范围之外"可用",有效地成为全局变量.

def bob():
    global me
    me = "locally defined"   # Defined locally but declared as global
    print me

bob()
print me     # Asking for a global variable
Run Code Online (Sandbox Code Playgroud)

所以上面的代码会给你:

locally defined
locally defined
Run Code Online (Sandbox Code Playgroud)

此外,由于python的本质,您还可以使用global在本地上下文中声明函数,类或其他对象.虽然我会反对它,因为如果出现问题或需要调试它会导致噩梦.

  • 在这种背景下,"全球"似乎与其他语言的"全球"不同.在Python中,"全局"引用仍然在模块的范围内,需要从该模块外部引用为"module.global_var",而不是像人们预期的那样简单地引用"global_var". (55认同)
  • @juice - 在Python中,没有在所有命名空间中自动定义的绝对`globals`(谢天谢地).正如您正确指出的那样,全局绑定到模块中的命名空间,但是它可以作为"from module import variable"或`import module.variable`导入到另一个模块中.在第一种情况下,导入会使变量可以作为`variable`访问,而不需要引用为`module`.如果它被认为是模块范围内的全局,将取决于它的导入位置.另请参阅`nonlocal`作为python 3中与范围相关的新关键字. (16认同)
  • @RobinNewhouse关于SO的一些问题已经涵盖[http://stackoverflow.com/a/485020/125801] [主题](http://stackoverflow.com/a/19158418/125801)和其他非SO [物品](http://c2.com/cgi/wiki?GlobalVariablesAreBad). (5认同)
  • 你能解释为什么全局变量不是一个好的解决方案吗?我经常听到这个,但在我目前的项目中,他们似乎正在做我需要他们做的事情.有什么比我更没有想到的险恶吗? (3认同)

Ivo*_*zel 208

虽然您可以在不使用global关键字的情况下访问全局变量,但如果要修改它们,则必须使用global关键字.例如:

foo = 1
def test():
    foo = 2 # new local foo

def blub():
    global foo
    foo = 3 # changes the value of the global foo
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您只是访问列表sub.

  • 有一个警告:`foo = 3` 没有全局作用,但是 foo 在 `blub` 函数作用域中再次本地定义并且不会修改原始 foo 变量。这让我很困惑。 (4认同)
  • @chhantyal 如果通过作品你的意思是它不会抛出错误,你是正确的,但在 Ivo Wetzel 的上下文中,它不会按预期运行。这种行为是有用途的,但通常不是程序员想要的。 (2认同)

pyc*_*uft 72

这是访问名称和在范围内绑定它之间的区别.

如果您只是查找变量来读取其值,则可以访问全局和本地范围.

但是,如果您为名称不在本地范围内的变量分配,则将该名称绑定到此范围(如果该名称也作为全局存在,则会隐藏该名称).

如果您希望能够分配全局名称,则需要告诉解析器使用全局名称而不是绑定新的本地名称 - 这就是'global'关键字的作用.

绑定块中的任何位置都会导致该块中的所有名称都被绑定,这可能会导致一些相当奇怪的后果(例如,UnboundLocalError突然出现在以前工作的代码中).

>>> a = 1
>>> def p():
    print(a) # accessing global scope, no binding going on
>>> def q():
    a = 3 # binding a name in local scope - hiding global
    print(a)
>>> def r():
    print(a) # fail - a is bound to local scope, but not assigned yet
    a = 4
>>> p()
1
>>> q()
3
>>> r()
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    r()
  File "<pyshell#32>", line 2, in r
    print(a) # fail - a is bound to local scope, but not assigned yet
UnboundLocalError: local variable 'a' referenced before assignment
>>> 
Run Code Online (Sandbox Code Playgroud)

  • 非常违反直觉,很难相信这是有效的 python 代码 (2认同)

kin*_*all 51

其他答案回答了你的问题.关于Python中名称的另一个重要事项是,它们在每个范围的基础上是本地的或全局的.

考虑一下,例如:

value = 42

def doit():
    print value
    value = 0

doit()
print value
Run Code Online (Sandbox Code Playgroud)

您可能猜测该value = 0语句将分配给局部变量,而不会影响在doit()函数外声明的同一变量的值.您可能会更惊讶地发现上面的代码无法运行.print value函数内部的语句产生一个UnboundLocalError.

原因是Python已经注意到,在函数的其他地方,您指定了名称value,并且也value没有声明global.这使它成为一个局部变量.但是当您尝试打印它时,尚未定义本地名称.在这种情况下, Python 不会像其他语言那样回归到将名称作为全局变量查找.实际上,如果在函数中的任何位置定义了同名的局部变量,则无法访问全局变量.

  • 感谢您指出了这一点。因此,只要您的本地范围没有分配给存在于它之外的名称,那么本地范围中的引用将使用外部名称。但是,如果您在函数中的任何地方分配了该名称,则该局部范围内的引用,即使在局部分配之前,也不要向外看。 (2认同)
  • 在其他语言中,这似乎被称为"吊装",例如:https://github.com/shichuan/javascript-patterns/blob/master/general-patterns/hoisting.html (2认同)

use*_*312 14

访问名称和分配名称是不同的.在您的情况下,您只是访问一个名称.

如果分配给函数中的变量,则假定该变量是本地变量,除非您将其声明为全局变量.如果没有,则假定它是全球性的.

>>> x = 1         # global 
>>> def foo():
        print x       # accessing it, it is global

>>> foo()
1
>>> def foo():   
        x = 2        # local x
        print x 

>>> x            # global x
1
>>> foo()        # prints local x
2
Run Code Online (Sandbox Code Playgroud)


mar*_*nas 7

  • 您可以访问不带关键字的全局关键字 global
  • 为了能够修改它们,您需要明确声明关键字是全局的.否则,关键字将在本地范围内声明.

例:

words = [...] 

def contains (word): 
    global words             # <- not really needed
    return (word in words) 

def add (word): 
    global words             # must specify that we're working with a global keyword
    if word not in words: 
        words += [word]
Run Code Online (Sandbox Code Playgroud)