今日内容
一、函数对象
函数是第一类对象,即函数可以像变量一样使用
特点:
1、可以被引用
2、可以当作参数传递
3、返回值可以是函数
4、可以当作容器类型的元素
例:
def foo():
print('foo')
def bar():
print('bar')
dic={
'foo':foo,
'bar':bar,
}
while True:
choice=input('>>: ').strip()
if choice in dic:
dic[choice]()
二、函数嵌套
2.1函数嵌套的调用:
例:
def max2(x,y):
if x > y:
return x
else:
return y
def max4(a,b,c,d):
res1 = max2(a,b)
res2 = max2(res1,c)
res3 = max2(res2,d)
return res3
print(max4(11,22,33,44))
2.2函数嵌套的定义:
def f1():
def f2():
def f3():
print("hello")
f3()
f2()
f1()
三、名称空间与作用域
3.1名称空间
1、什么是名称空间:
存放名字的地方,有三种名称空间,py文件中一定会产生内置名称空间、全局名称空间,但不一定会产生局部内存空间
(内置名称空间,全局名称空间,局部内存空间)
2、名称空间的加载顺序:
1、内置名称空间:启动python器就会首先加载内置名称空间
2、全局名称空间:执行python文件的时候,基于代码内容,识别语法是加载全局名称空间
3、局部名称空间:执行python文件的时候,识别语法中有函数的话才会加载局部内存空间
3、名称空间的查找顺序:
(内置(全局(内置)))
需要注意的是:在全局无法查看局部的,在局部可以查看全局的,如下示例:
max =1
def f1():
max=2
def f2():
max=3
print(max)
f2()
f1()
print(max) #这时max的值会先从本层——》外层——》全局——》内置
3.2作用域
1、什么是作用域:作用域即范围
全局范围:内置名称空间和全局名称空间属于这个范围,特点:全局存活,全局有效
局部范围:局部名称空间属于这个范围,特点:临时存活,局部有效
2、作用域关系是在函数定义阶段就已经确定的,和函数的调用位置无关。
例:x=1
def f1():
def f2():
print(x)
return f2
x=100
def f3(func):
x=2
func()
x=10000
f3(f1()) #这时打印出来的时10000,当函数内没有x时就会去全局找,而X这个变量在全局内最后定为10000
3、阶级作用域的代表名字:
LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
locals(当前函数本层) 是函数内的名字空间,包括局部变量和形参
enclosing(本层函数与全局作用域之间的函数层) 外部嵌套函数的名字空间(闭包中常见)
globals(全局层次) 全局变量,函数定义所在模块的名字空间
builtins(内置层次) 内置模块的名字空间
4、global与nonlocal关键字
1、global例:
x = 10
y = 20
def f1():
x = 30
y = 40
def f2():
global x,y #声明本层用的X,Y是全局名称空间中的x,y
print(x,y)
f2()
f1() #这时打印的是10,20
2、nonlocal例:
a = 10 # a1 当前模块全局变量
def outer():
a = 9 # a2 outer局部变量
def inner():
nonlocal a #用于在函数内层中改变外层函数变量
a = 8 # a3 既是inner局部变量,又是外层outer局部变量
print(a) # a3 8,在inner的局部作用域中找到了a3
inner() # inner()函数结束,a3作为外层变量(outer局部变量)被保留成为a2
print(a) # a2 8,在outer局部作用域中找到a2(在inner中被改变)
outer() # outer()函数结束,a2作为outer局部变量被释放
print(a) # a1 10,在当前模块全局作用域中找到了a1
四、闭包函数
4.1什么是闭包
内部函数包含对外部作用域而非全局作用域的引用(一个函数把另一个函数封闭包起来)
之前我们都是通过参数将外部的值传给函数,闭包提供了另外一种思路
4.2闭包的意义与应用
1、闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,
这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
2、应用
例:
def f1(x):
def f2():
print(x)
return f2
f = f1(111)
f()
f = f1(222)
f()
五、装饰器
5.1为何要用装饰器
开放封闭原则:对修改封闭,对扩展开放
5.2什么是装饰器
装饰他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式
装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能