4、高阶函数
命名空间
又名name space, 顾名思义就是存放名字的地方,存什么名字呢?举例说明,若变量x=1,1存放于内存中,那名字x存放在哪里呢?名称空间正是存放名字x与1绑定关系的地方
名称空间共3种,分别如下
- locals: 是函数内的名称空间,包括局部变量和形参
- globals: 全局变量,函数定义所在模块的名字空间
- builtins: 内置模块的名字空间
不同变量的作用域不同就是由这个变量所在的命名空间决定的。
作用域即范围
- 全局范围:全局存活,全局有效
- 局部范围:临时存活,局部有效
查看作用域方法 globals(),locals()
作用域查找顺序
LEGB:
L:locals ; E:enclosing相邻的 ; G:globls ; B:builtins
n = 10 def func(): n = 20 print('func:' ,n) #func:20 def func2(): n = 30 print(' func2' ,n) #func2:30 def func3(): print('func3:' , n) #func3:30 func3() func2() func()
LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
- locals 是函数内的名字空间,包括局部变量和形参
- enclosing 外部嵌套函数的名字空间
- globals 全局变量,函数定义所在模块的名字空间
- builtins 内置模块的名字空间
闭包
在函数里边又套了一层子函数,在子函数被返回了,就是当外层函数执行的时候子函数被返回了返回了内存地址;然后在外边执行这个子函数的时候它又引用了外边函数的这个变量,相当于这个子函数跟外层函数有某种扯不清的关系,这种关系就叫闭包。
关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数)。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。也就是说,内部函数会在外部函数返回后被执行。而当这个内部函数执行时,它仍然必需访问其外部函数的局部变量、参数以及其他内部函数。这些局部变量、参数和函数声明(最初时)的值是外部函数返回时的值,但也会受到内部函数的影响。
装饰器( 闭包+函数的重新赋值)
软件开发中的一个原则“开放-封闭”原则,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:
- 封闭:已实现的功能代码块不应该被修改
- 开放:对现有功能的扩展开放
实现装饰器知识储备:
1. 函数即“变量”
2. 高阶函数; a、把一个函数名当做实参传入另一个函数 ;b、返回值中包含函数名(不修改函数的调用方式)
3. 嵌套函数
高阶函数+嵌套函数=》装饰器
在不改变原代码前提下给它加一个装饰的功能:搞一个高阶函数,把要修饰的当做参数传进去,然后在里边返回。
定义:本质是函数(装饰其他函数)就是为其他函数添加附加功能
原则:1.不能修改被装饰的函数的源代码;2.不能修改被装饰的函数的调用方式;
装饰器对它被装饰的函数是完全透明的,就是别人不知道你改了它的,没影响。
如:
编写装饰器,为每个函数加上统计运行时间的功能
提示:在函数开始执行时加上start=time.time()就可纪录当前执行的时间戳,函数执行结束后在time.time() - start就可以拿到执行所用时间
import time def deco(func): start_time = time.time() func() stop_time = time.time() print('the func run time is %s'%(stop_time - start_time)) def test1(): time.sleep(2) print('in the test1') deco(test1) #test1()加括号就是把它的运行结果传进去了; 这种调用方式改变了函数的调用方式。改变了test1的调用方式。test1=deco(test1) ---> test1();前提是把它修改成第二种形式的高阶函数加个return返回它的内存地址即它的返回值。 import time def timer(func): #timer(test1) func=test1 def deco(): start_time = time.time() func() #运行test1() stop_time = time.time() print('the func run time is %s'%(stop_time - start_time)) return deco #第二种形式的高阶函数 def test1(): time.sleep(2) print('in the test1') #print(timer(test1)) #返回的是deco的一个内存地址 test1 = timer(test1) #执行timer(test1)这个函数,把test1当做参数传进去;拿到一个返回结果deco; 代码走到这一步的时候会执行timer(test1),不会往下走了 test1() ## 实际上运行执行的是deco #既没有改变调用方式也没有改变原代码
#######初级装饰器 import time def timer(func): #timer(test1) func=test1 def deco(): start_time = time.time() func() #运行test1() stop_time = time.time() print('the func run time is %s'%(stop_time - start_time)) return deco @timer #--->> test1 = timer(test1) def test1(): time.sleep(2) print('in the test1') @timer #--->> test2 = timer(test2) def test2(): time.sleep(4) print('in the test2') test1() test2()
#####中级带参数装饰器 import time def timer(func): #timer(test1) func=test1 def deco(*args,**kwargs): start_time = time.time() func(*args,**kwargs) #运行test1() stop_time = time.time() print('the func run time is %s'%(stop_time - start_time)) return func #把函数的结果要给返回了 return deco @timer #--->> test1 = timer(test1) def test1(): time.sleep(2) print('in the test1') return 'from test1' @timer #--->> test2 = timer(test2) = deco test2(name,age)=deco(name,age) ==deco(arg1,arg2)-->func(arg1,arg2) def test2(name,age): time.sleep(4) print('test2',name,age) test1() test2('alex',22)
打印: in the test1 the func run time is 2.0001144409179688 test2 alex 22 the func run time is 4.0002288818359375
#####高级版 import time user,passwd = 'kris' , 'abc123' def auth(auth_type): #auth_type : 'local' print("auth func:" , auth_type) def outer_wrapper(func): def wrapper(*args, **kwargs): print("wrapper func args:" , *args,**kwargs) if auth_type == "local": username = input("Username:").strip() password = input("Password:").strip() if user == username and passwd == password: print("