课程链接:Python编程基础_中国大学MOOC(慕课) (icourse163.org)
目录
全局变量__name__
1. 每个模块都有的一个全局变量__name__
2. __name__的作用是获取当前模块的名称,如果当前模块是单独执行的,则其__name__的值就是__main__;否则,如果是作为模块导入,则其__name__的值就是模块的名字。
举例:
module.py脚本文件
print(__name__) # 输出:__main__
testmodule.pt脚本文件
import module
# 输出:module
注:当我们执行module.py时,会在屏幕上输出:__main__;而当我们执行testmodule.py时,则会在屏幕上输出:module
即module.py单独运行和作为模块导入时其__name__的值是不同的。
nonlocal关键字
在Python中,函数的定义可以嵌套,即在一个函数的函数体中可以包含另一个函数的定义。通过nonlocal关键字,可以使内层的函数直接使用外层函数中定义的变量。
使用nonlocal关键字示例:
def outer():
x = 10
def inner():
nonlocal x
x = 20
print('inner函数中的x值为:', x)
inner()
print('outer函数中的x值为:', x)
outer()
# 输出
'''
inner函数中的x值为: 20
outer函数中的x值为: 20
'''
通过“nonlocal x”声明在inner函数中使用outer函数中定义的变量x,而不是重新定义一个局部变量x。
1、内层函数使用外层函数中定义的变量,应使用( )关键字。
A.local
B.nonlocal
C.global
D.nonglobal
正确答案:B
解析:内层函数使用外层函数中定义的变量,则在使用前应加上nonlocal声明;
一个函数要使用全局变量,则在使用前应在函数中加上global声明。
注:如果在内层函数中只是获取外层函数中所定义变量的值、而不需要修改该变量的值,则也可以省去nonlocal声明;同样,如果在一个函数中只是获取全局变量的值、而不需要修改全局变量的值,则也可以省去global声明。但为了增强程序可读性,建议在编写程序时无论是否需要修改外层函数中所定义变量的值或全局变量的值,都将nonlocal和global声明写上。
2、内层函数要使用外层函数定义的变量,必须使用nonlocal关键字。
A.正确
B.错误
正确答案:B
解析:如果在内层函数中只是获取外层函数中所定义变量的值、而不需要修改该变量的值,则也可以省略nonlocal声明。但同第1题的解析,为了增强程序可读性,建议无论是否需要修改外层函数中所定义变量的值,都将nonlocal声明写上。
闭包
如果内层函数使用了外层函数中定义的局部变量,并且外层函数的返回值是内层函数的引用,就构成了闭包。
定义在外层函数中但由内层函数使用的变量被称为自由变量。
一般情况下,如果一个函数结束,那么该函数中定义的局部变量就都会释放。然而,闭包是一种特殊情况,外层函数在结束时会发现其定义的局部变量将来会在内层函数中使用,此时外层函数就会把这些自由变量绑定到内层函数。
因此,所谓闭包,实际上就是将内层函数的代码以及自由变量(外层函数定义、但会由内层函数使用)打包在一起。
示例:
def outer(x): # 定义函数outer
y = 10 # 定义局部变量y并赋值
def inner(z): # 在outer函数中定义嵌套函数inner
nonlocal x, y #nonlocal声明,使用的是在outer函数中定义的x,y,而不会定义新的x,y
return x+y+z #返回x+y+z的结果
return inner # 返回嵌套函数Inner的引用
f = outer(5) # 将返回的Inner函数赋值给f
g = outer(50) # 将返回的Inner函数赋值给给g
print('f(20)的值为:', f(20))
print('g(20)的值为:', g(20))
print('f(30)的值为:', f(30))
print('g(30)的值为:', g(30))
'''
f(20)的值为: 35
g(20)的值为: 80
f(30)的值为: 45
g(30)的值为: 90
'''
闭包的主要作用在于可以封存函数执行的上下文环境。例如,通过两次调用outer函数形成了两个闭包,这两个闭包具有相互独立的上下文环境(一个闭包中x=5、y=10,另一个闭包中x=50、 y=10),且每个闭包可多次调用。
1. 外层函数中定义的局部变量被内层函数使用,则每调用一次外层函数则会形成一个闭包。
A.正确
B.错误
正确答案:B
解析:外层函数必须返回内层函数的引用,这样每调用一次外层函数才会形成一个闭包。
装饰器
1. 利用装饰器,可以在不修改已有函数的情况下向已有函数中注入代码,使其具备新的功能
2. 一个装饰器可以为多个函数注入代码,一个函数也可以注入多个装饰器的代码
3. 利用装饰器可以将日志处理、执行时间计算等较为通用的代码注入到不同的函数中,从而使得代码更加简洁。
示例1:
def deco1(func):
def inner1(*args, **kwargs):
print('deco1 begin')
func(*args, **kwargs)
print('deco1 end')
return inner1
def deco2(func):
def inner2(*args, **kwargs):
print('deco2 begin')
func(*args, **kwargs)
print('deco2 end')
return inner2
@deco1
def f1(a,b):
print('a+b=', a+b)
@deco1
@deco2
def f2(a,b,c):
print('a+b+c=', a+b+c)
if __name__ == '__main__':
f1(3,5)
f2(1,3,5)
# 输出
'''
deco1 begin
a+b= 8
deco1 end
deco1 begin
deco2 begin
a+b+c= 9
deco2 end
deco1 end
'''
示例2
def deco3(func):
def inner3(x,y):
print('deco3 begin')
func(x,y)
print('deco3 end')
return inner3
def deco4(func):
def inner4():
print('deco4 begin')
func()
print('deco4 end')
return inner4
@deco3
def f1(a,b):
print('a+b=', a+b)
@deco4
def f2():
print('f2 is called')
if __name__ == '__main__':
f1(3,5)
f2()
# 输出
'''
deco3 begin
a+b= 8
deco3 end
deco4 begin
f2 is called
deco4 end
'''
注:deco3只能用于装饰带两个参数的函数,deco4只能用于装饰没有参数的函数