在Python中使用“全局”关键字


285

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

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

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

即使没有,看起来一切都很好global。我能够毫无问题地访问全局变量。

我有什么想念的吗?另外,以下是Python文档中的内容:

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

尽管形式参数和类定义对我来说很有意义,但我无法理解对循环控制目标和函数定义的限制。


1
我认为你是用PHP这就需要使用global关键字的困惑- Python文档证实了这一点- basicly如果不在本地上下文中定义它被视为全球
tobyodavies

11
小心你的措辞:Python没有的功能,一个单独的命名空间(这将意味着你可以有def foo(): ...,并foo = ...在同一时间)。它确实为每个函数调用创建了一个新作用域。(但是,这与世界上其他所有远程高级语言有何不同?)

Answers:


366

关键字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在局部上下文中声明函数,类或其他对象。尽管我会建议不要这样做,因为如果出现问题或需要调试,它会引起噩梦。


59
在这种情况下,“全局”似乎不同于其他考虑“全局”的语言。在Python中,“全局”引用仍在模块范围内,需要从该模块外部将其引用为“ module.global_var”,而不是像人们期望的那样简单地引用“ global_var”。
果汁

17
@juice-在Python中,并没有globals跨所有名称空间自动定义“ 绝对”的东西(谢天谢地)。正如您正确指出的那样,全局已绑定到模块内的名称空间,但是可以将其作为from module import variable或导入另一个模块import module.variable。在第一种情况下,导入将使变量可访问为,variable而无需引用module.。如果在模块范围内将其视为全局变量,则取决于其导入位置。另请参见nonlocalpython 3中与作用域相关的新关键字
。– Unode

3
您能否解释为什么全局变量不是一个好的解决方案?我经常听到这一点,但是在我当前的项目中,他们似乎只是在做我需要他们做的事情。我有没有想过的险恶的东西?
罗宾·纽豪斯

5
@RobinNewhouse关于SO的一些问题已经涵盖了 主题和其他非SO 文章
取消播放

213

虽然可以在不使用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


3
请注意,foo = 3没有全局工作,但是foo在blub函数作用域中再次在本地定义,并且不会修改原始foo变量。这让我很困惑。
chhantyal

1
@chhantyal,如果按工作原理表示您没有错误,那么您是正确的,但是在Ivo Wetzel的上下文中,它将无法正常工作。这种行为有很多用途,但通常不是程序员想要的。
democidist

77

这是访问名称并将其绑定到作用域之间的区别。

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

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

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

非常违反直觉,很难相信这是有效的python代码
PlsWork '19

52

其他答案回答您的问题。关于Python的名称,要知道的另一件重要事情是,就每个作用域而言,它们是局部的还是全局的。

考虑一下,例如:

value = 42

def doit():
    print value
    value = 0

doit()
print value

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

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


1
感谢您指出了这一点。因此,只要您的本地范围未分配给存在于其外部的名称,那么本地范围内的引用将使用外部名称。但是,如果您确实在函数中的任何位置分配了该名称,则即使在本地分配之前,该本地作用域中的引用也不会向外查找。
德米特里·明科夫斯基

1
确实,您已经掌握了。global(或nonlocal在Python 3.x中)覆盖此行为,并允许您重新分配外部名称。
kindall

2
在其他语言中,这似乎被称为“吊装”,例如:github.com/shichuan/javascript-patterns/blob/master/…–
Dmitry

为了雪上加霜的是,变量与关键字的新JavaScript中声明let悬挂。
kindall

访问用声明的全局变量更快global还是没关系?
马托

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

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]

2

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


1

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


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"

ikostia是枚举所有你不能用“X”的事情已经使用的全局- docs.python.org/reference/...
pycruft

1
@Unode:我只是示范NikhilRathod在他的报价中提到的所有情况。
ikostia 2011年

0

全局使变量“全局”

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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.