局部变量(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函数内的局部变量了。