python函数(二)
变量的作用域
1、局部变量与全局变量
在函数内创建的变量被称为局部变量,这类变量的生命周期与函数相同,当函数执行完毕时,变量也就随之消失。
此类变量只能在函数内部调用,函数外不能调用该变量。
def getName():
name = 'Jerry'
print('函数getName()中的name:' + name)
getName()
# print(name) 在函数外引用函数内定义的name变量,就会直接报错:NameError: name 'name' is not defined
打印结果:
函数getName()中的name:Jerry
全局变量是定义在函数之外的变量,该函数在函数内外都可以调用。全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序(函数)。
NAME = 'Serra'
def getName():
print('在函数内调用全局变量NAME:' + NAME)
getName()
print('在函数外调用全局变量NAME:' + NAME)
打印结果:
在函数内调用全局变量NAME:Serra
在函数外调用全局变量NAME:Serra
2、存在同名的全局变量与局部变量
变量调用的基本规则就是:python总是会去寻找距离最近的声明变量。这种距离最近不是上下文的距离,而是在调用变量时,在当前作用域寻找声明变量,如果没有,则向上一层寻找声明变量,直至找到该名称的变量。
name = 'global name'
def outer():
name = 'outer name'
def inner1():
name1 = 'inner name'
def inner2():
print('在Inner2函数中找到的name是:' + name)
return inner2
return inner1
outer()()()
打印结果:
在Inner2函数中找到的name是:outer name
在上述例子中,outer函数内嵌套着inner1函数,inner1函数内又嵌套着inner2函数。inner1函数将inner2函数作为返回值,outer函数将inner1函数作为返回值。
这个函数的调用过程如下:
- outer(),返回值为inner1,此时的返回值是一个inner1函数;
- outer()(),相当于调用outer函数中的inner1函数,此时inner1函数的返回值为inner2函数,到这一步我们获得的是inner2函数;
- outer()()(),相当于调用上一步获得的inner2函数,得到打印结果。
从这个例子中可以看到,在调用变量时,程序会一层层地向上查找,直到找到相应名称的变量。
3、global与nonlocal关键字
在一般的变量调用中,修改函数内部定义的变量,对同名的全局变量并不会产生影响。
name = 'global name'
def bar():
name = 'bar\'s name'
print('函数内的name:' + name)
bar()
print('函数外的name:' + name)
打印结果:
函数内的name:bar's name
函数外的name:global name
可以看到,在函数内修改name的值,这种修改只限于在调用函数时;当函数执行完毕后,调用的name变量的值依然没有改变。
但是python中提供了global关键字,该关键字用于函数内部,引用形式:'global 变量名'。使用该关键字时,表示函数内部引用的是全局变量。
name = '全局变量中定义的name...'
def foo():
global name
name = 'foo\'s name'
foo()
print('调用foo()后,全局变量中定义的name:' + name)
打印结果:
调用foo()后,全局变量中定义的name:foo's name
可以看到,使用了global关键字后,foo函数修改的name就是全局变量中的name了。
在函数中出现了global关键字后,这之后的变量指向的都是全局中的变量。因此,函数如果有自己的私有变量(局部变量)时,不要和global变量重名,否则会使调用出现错误;global关键字要写在函数体的最开始部分。
无论在函数内部定义了多少层函数,global关键字命名的变量永远指向全局变量。
此外,python还提供了一个nonlocal关键字,用来在内部函数调用外层函数的变量。
def foo():
name = 'foo\'s name...'
def bar():
nonlocal name # 使用nonlocal关键字调用foo函数中的name变量
name = '更名为:bar\'s name...' # 此时修改的是foo中的name变量
bar() # 在foo()函数内部调用bar()
print(name)
foo()
打印结果:
更名为:bar's name...
可以看到,在foo函数内部定义了一个bar函数,nonloca name
这一句表示调用的是bar函数外层、也就是foo函数的name变量,并在bar函数内部对该变量的值进行了修改。在foo中运行bar函数,调用foo的同时也调用了内部的bar函数。因此输出的name就变成了更改过的值。
需要注意的一点:nonlocal关键字仅能调用函数外层的局部变量,不能调用全局变量。有人会问,既然nonlocal关键字能够调用外层变量,那么当函数外层只有全局变量时,能否用nonlocal调用全局变量呢?
name = 'global name'
def foo():
nonlocal name
name = 'foo\'s name'
print('当前的name:' + name)
无打印结果,程序会报错:无nonlocal变量绑定
SyntaxError: no binding for nonlocal 'name' found
nonlocal并不能调用全局变量。