在Python中使用“global”关键字

时间:2011-01-14 16:11:04

标签: python global-variables

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

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

>>> sub = ['0', '0', '0', '0']
>>> def getJoin():
...     return '.'.join(sub)
...
>>> getJoin()
'0.0.0.0'

即使没有global,似乎工作正常。我能够毫无问题地访问全局变量。

我错过了什么吗?此外,以下内容来自Python文档:

  

全局声明中列出的名称   不得被定义为正式的   参数或for循环控制   目标,类定义,功能   定义或导入声明。

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

12 个答案:

答案 0 :(得分:345)

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

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

bob()
print me     # Asking for a global variable

以上将给你:

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

如果你使用global语句,变量将在函数范围之外“可用”,有效地成为一个全局变量。

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

bob()
print me     # Asking for a global variable

所以上面的代码会给你:

locally defined
locally defined

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

答案 1 :(得分:200)

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

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

def blub():
    global foo
    foo = 3 # changes the value of the global foo

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

答案 2 :(得分:67)

这是在范围内访问名称和binding之间的区别。

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

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

如果您希望能够分配全局名称,则需要告诉解析器使用全局名称而不是绑定新的本地名称 - 这就是'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
>>> 

答案 3 :(得分:48)

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

考虑这一点,例如:

value = 42

def doit():
    print value
    value = 0

doit()
print value

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

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

答案 4 :(得分:13)

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

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

>>> 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

答案 5 :(得分:6)

  • 您可以访问不含关键字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]

答案 6 :(得分:2)

在函数外部声明的任何变量都假定为全局变量,只有在从函数内部(构造函数除外)声明它们时才必须指定变量是全局的。

答案 7 :(得分:0)

这意味着您不应该执行以下操作:

x = 1

def myfunc():
  global x

  # formal parameter
  def localfunction(x):
    return x+1

  # import statement
  import os.path as x

  # for loop control target
  for x in range(10):
    print x

  # class definition
  class x(object):
    def __init__(self):
      pass

  #function definition
  def x():
    print "I'm bad"

答案 8 :(得分:0)

Global将变量设为“Global”

def out():
    global x
    x = 1
    print(x)
    return


out()

print (x)

这使得'x'就像是函数外的正常变量。如果你取出全局,那么它会产生错误,因为它无法在函数内打印变量。

def out():
     # Taking out the global will give you an error since the variable x is no longer 'global' or in other words: accessible for other commands
    x = 1
    print(x)
    return


out()

print (x)

答案 9 :(得分:0)

我将举一个简单的例子: 想想这段代码:

myVar = 0 
print (myVar )      # 01 line: returns 0

def func():
    myVar  = "def"
    print (myVar )

func()              # 02 line: returns def
print (myVar )      # 03 line: returns 0

正如您所看到的,最后一行代码将返回0,因为在函数内部 myVar 变量未被重新分配,它刚刚被修改,只有在函数时它才会改变在不影响主myVar变量的情况下调用,因为它在我们的函数内部定义(意味着它是局部变量),但是使用全局关键字:

 myVar  = 0 
print (myVar )       # 01 Line : returns 0

def func():
    global myVar 
    myVar  = "def"
    print (myVar )

func()               # 02 Line : returns def
print (myVar )       # 03 Line : returns def

我们实际上命令python,def中的这个变量不是本地的,使用名为 myVar 的全局变量来改变它。

答案 10 :(得分:0)

在Python常见问题解答中对此进行了很好的解释

  

Python中局部变量和全局变量的规则是什么?

     

在Python中,仅在函数内部引用的变量是隐式全局的。如果在函数体内任何位置为变量分配了值,除非明确声明为全局变量,否则假定该变量为局部变量。

     

尽管起初有些令人惊讶,但片刻的考虑解释了这一点。一方面,要求global分配变量可以防止意外副作用。另一方面,如果所有全局引用都需要global,那么您将一直使用global。您必须将对内置函数或导入模块的组件的每个引用声明为global。这种混乱会破坏global声明对识别副作用的有用性。

https://docs.python.org/3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python

答案 11 :(得分:0)

global 使变量对 模块 中的所有内容可见,模块化作用域,就像您在模块的顶层定义它一样本身。它在模块外是不可见的,并且在设置之后才能从模块中导入,所以不要打扰,这不是它的用途。

global 何时可以解决实际问题? (注意:仅在 Python 3 上检查。)

# Attempt #1, will fail
# We cannot import ``catbus`` here
# as that would lead to an import loop somewhere else,
# or importing ``catbus`` is so expensive that you don't want to 
# do it automatically  when importing this module

top_level_something_or_other = None

def foo1():
    import catbus
    # Now ``catbus`` is visible for anything else defined inside ``foo()`` 
    # at *compile time*
    bar()  # But ``bar()`` is a call, not a definition. ``catbus`` 
           # is invisible to it.

def bar():
    # `bar()` sees what is defined in the module
    # This works:
    print(top_level_something_or_other)
    # This doesn't work, we get an exception: NameError: name 'catbus' is not defined
    catbus.run()

这可以通过 global 解决:

# Attempt #2, will work
# We still cannot import ``catbus`` here
# as that would lead to an import loop somewhere else,
# or importing ``catbus`` is so expensive that you don't want to 
# do it automatically  when importing this module

top_level_something_or_other = None

def foo2():
    import catbus
    global catbus  # Now catbus is also visible to anything defined 
                   # in the top-level module *at runtime* 
    bar()

def bar():
    # `bar` sees what is defined in the module and when run what is available at run time
    # This still works:
    print(top_level_something_or_other)
    # This also works now:
    catbus.run()

如果 bar() 像这样在 foo 中定义,则不需要:

# Attempt 3, will work
# We cannot import ``catbus`` here
# as that would lead to an import loop somewhere else,
# or importing ``catbus`` is so expensive that you don't want to 
# do it automatically  when importing this module

top_level_something_or_other = None

def foo3():

    def bar():
        # ``bar()`` sees what is defined in the module *and* what is defined in ``foo()``
        print(top_level_something_or_other)
        catbus.run()

    import catbus
    # Now catbus is visible for anything else defined inside foo() at *compile time*
    bar()  # Which now includes bar(), so this works

通过在 bar() 之外定义 foo(),可以将 bar() 导入到可以直接导入 catbus 的东西中,或者模拟它,例如在单元测试中。

global 是一种代码异味,但有时您需要的是像 global 这样的肮脏黑客。无论如何,“全局”对它来说是一个坏名字,因为在 python 中没有全局作用域这样的东西,它一直是模块。