python教程之全局与局部变量

局部变量(Local Variable)

有句谚语叫盲人摸象,盲人们看不到整体的大象,他们摸到什么就说大象像什么。这里将要说的是一个局部的概念。前面讲了函数的定义,在函数内部也是可以定义变量的。不过,如果想在函数外面使用函数里面的变量,那是无法使用的,就像你在老家讲的方言,到了外地,别人无法听懂,所以老家方言无法使用。接下来,我们“以身试法”,看看在函数外面使用函数内部定义的变量会怎么样,以下是代码示例:

>>> def func1():       # 定义函数,名称为func1
  number = 1           # 定义变量,名称为number
  print(number)

  
>>> print(number)
Traceback (most recent call last):
  File "<pyshell#61>", line 1, in <module>
    print(number)
NameError: name 'number' is not defined
>>>

上面的代码“强行”打印曾经在函数内部定义的变量number的值,然而并没有什么用处。Python给你提示了一个叫NameError的错误。在第10行,提示了名字‘number’没有定义。

由于number这个变量,它是在函数内部定义的,它只是局限于在函数内使用,所以它叫局部变量,也叫本地变量。既然有局部变量,那相对而言,是不是有全局变量呢?答案是肯定的,它能贯穿全局,可“厉害”着呢。

全局变量(Global Variable)

当你爬上一座高峰,或许能看到一座小城市的整体面貌。这叫一览众山小,说的是一个全局的概念。相对于在函数内定义的变量,在函数外部定义的变量叫全局变量。如果不需要修改这个全局变量的值,那么可以直接引用这个全局变量的值。以下是一个例子:

>>> number2 = 10                  #  定义全局变量
>>> def func2():                  # 定义函数
  number3 = number2 + 10    # 定义局部变量,同时赋值
  print(number3)

  
>>> number2
10
>>> number3

在上面的func2中有两个变量,一个number3是局部变量,一个number2是函数外部的变量,由于不需要修改它的值,所以可以直接引用它的值。如果我们要在函数内部修改number2的值,则要用global申明一下它是全局变量。global 在英文中就是全局的意思,在Python中用它来申明一个变量为全局变量。以下示例修改了number2的值。

>>> number2 = 10               # 定义全局变量
>>> def double():                # 定义函数
  global number2            # 申明number2为全局变量
  number2 = number2 * 2  

  
>>> double()
>>> number2
20
>>>

在上面的第3行是申明number2为全局变量的语句,如果不申明,将会报错,到底会报什么错误,我们来实践一下:

>>> number3 = 0               # 定义全局变量
>>> def double():               # 定义函数 
  number3 = number3 * 2       # 试图修改变量的值

  
>>> double()
Traceback (most recent call last):
  File "<pyshell#86>", line 1, in <module>
    double()
  File "<pyshell#85>", line 2, in double
    number3 = number3 * 2
UnboundLocalError: local variable 'number3' referenced before assignment
>>>

在上面的代码中,定义函数的时候是不会出错的,但是在调用函数的时候出错了,显示的是未绑定的局部错误(UnboundLocalError)。 我们来假设一下,如果number3是本地变量,使用它时应该先定义,而第3行并没有事先定义number3就直接让它乘以2。如果number3是全局变量,第3行试图修改这个全局变量的值,但并没有申明number3为全局变量。

上面的两种假设说明number3即不是本地变量也不是外地变量,就像你到了外地,即不是外地人,也不是本地人一样,这里就产生了矛盾,所以出错是必然的。其实在第3行代码,Python试图把number3当成本地变量,但在使用它时并未赋值,所以显示了local variable ‘number3’ referenced before assignment这行英文(本地变量在赋值前就被引用)。

还有一种情况,那就是在函数内部定义了和外部同名的变量,那么优先使用函数内部的这个变量。请输入以下代码,体验一下这种情况。

>>> number5 = 10           # 定义全局变量
>>> def test1():           # 定义函数test1
  number5 = 20             # 定义局部变量
  print(number5)

  
>>> test1()
20
>>> number5               # number5的值并没有改变
10

上面第9行试图显示number5的值,结果是10,并不是函数内部那个number5的值。这说明函数内定义的number5的确是局部变量,而外部的number5的值丝毫没有改变。

我们应该尽量减少在函数内部使用全局变量。一般情况下,应该使用返回值让函数和它外层代码建立联系。函数是有返回值的,关于返回值的概念,下次再讲解。

nonlocal变量(nonlocal Variable)

前面说了全局变量和本地变量,还有一种特殊的情况,即在函数中又定义了一个函数这种情况。 如果在内部函数中要修改上层那个函数的值的话,那么申明变量的类型应该为nonlocal。先看看下面的例子:

>>> def zsum(x,y):
  z = x + y
  def func():          # 在函数中又定义了一个函数
    nonlocal z   # 申明z为nonlocal变量
    z = z * 2
  func()               # 调用func函数
  print(z)             # 打印z的值

>>> zsum(3,7)
20

在上面的代码中,func函数是在一个函数中所定义的内部函数。它要修改z的值,但是z并不是全局变量,所以不能申明它为全局变量。Python规定要申明它为nonlocal变量才能修改它的值。nonlocal字面意思是非本地的意思。如果不申明z为nonlocal变量,则运行到z = z * 2时肯定会出错。如果直接让z = 2 ,那么不会出错,这是由于Python把它当成func函数内的局部变量了。