一、什么是闭包函数
1.1完整定义:
定义在函数内部的函数,并且该函数包含对外部函数作用域的引用
闭包函数提供了另一种为函数体传值的方式:外层函数包一个值给他
def outter(): x=1 # 外部传一个值给内部函数 def inner(): print(x)# 需要一个值 return inner # return打破层级的限制
二、装饰器
2.1为什么要有装饰器?
软件一旦上线,就应该遵守开放封闭原则:对功能升级开放,不允许修改源代码以及调用方式
2.2装饰器的简单版本
import time def my_time(): # 原本函数 time.sleep(0.5) print('统计时间') def warpper(func):# 定义装饰器 def inner(): start_time=time.time() my_time() stop_time=time.time() print(stop_time-start_time) return inner res=warpper(my_time) res()
2.3装饰器的升级版
一、加入返回值,并支持调多个函数
import time def my_time(): time.sleep(0.5) print('统计时间') return 123 # my_time函数有返回值 def warpper(func): def inner(): start_time=time.time() res2=func()# 被调用的函数inner内部加返回值;并且用func来代替具体函数名,从而调用更多不同函数 stop_time=time.time() print(stop_time-start_time) return res2 #被调用函数inner内部加return return inner my_time=warpper(my_time) res=my_time() print(res)
my_time函数有返回值,而my_time()调用的是inner内部的函数,而他无返回值,所以要加
二、当出现有参函数时
import time def my_time(name): # 出现有参函数 time.sleep(0.5) print('统计时间') return 123 def warpper(func): def inner(*args,**kwargs): # 被调用的函数加入可变参数 start_time=time.time() res2=func(*args,**kwargs) # 加入可变参数 stop_time=time.time() print(stop_time-start_time) return res2 return inner my_time=warpper(my_time) res=my_time('wuxi') #此处必须指定参数 print(res)
三、装饰器的基本形式产生
def warpper(func): def inner(*args,**kwargs): print('此处填写要加入的功能') res2=func(*args,**kwargs) print('此处填写要加入的功能') return res2 return inner
正常我们情况下查看函数的一些信息的方法(原来的函数的函数名;原来的函数的注释)在此处都会失效。都会返回装饰函数的函数名和注释,如何使用户查看不出该函数被装饰过呢?
采用from functools import wraps
@warps方法
from functools import wraps def outter(func): @wraps(func) def inner(*args,**kwargs): # * **在形参中使用 # 执行被装饰函数之前你可以做的操作 res = func(*args,**kwargs) # * **在实参中使用 # 执行被装饰函数之后你可以做到操作 return res return inner @outter def index(username,*args,**kwargs): """index注释""" pass print(index) 装饰器修复技术 1.返回原来的函数的函数名 2.返回原来的函数的注释
三、装饰器语法糖
@+装饰器名。写在"装饰器"下和需要调用的函数上面。
方便人直接调用函数
def warpper(func): def inner(*args,**kwargs): res2=func(*args,**kwargs) return res2 return inner @warpper #index=warpper(index) # index=inner def index(): print('...') index() #@warpper 把正下方的紧挨着的函数名当做参数传入装饰器,并赋值给该函数
现在只需直接调用index。如果index函数有返回值的话,要赋值一下再print
多个语法糖叠加
装饰时:从下往上 执行时:从上往下 @outter1#index=outter(func2) @outter2#func2=outter2(func1) @outter3#func1=outter3(index)
有参装饰器(装饰器最复杂的版本)
def wrappers(data): # data = 'file' def outter(func): def inner(*args,**kwargs): if data == 'file': # 执行被装饰函数之前你可以做的操作 res = func(*args,**kwargs) # * **在实参中使用 # 执行被装饰函数之后你可以做到操作 return res return inner return outter
3.1现在来写一个认证装饰器
import time d={ 'username':None, } def outter(func): def inner(*args,**kwargs): if d['username']: res = func(*args, **kwargs) return res else: username=input('用户名:>>>').strip() password=input('密码:>>>').strip() if username =='wuxi' and password== '123': print('登录成功') d['username']=True res=func(*args,**kwargs) return res else: print('用户名或密码错误') return inner @outter# inner=outter(index) #index=inner def index(): time.sleep(0.1) return 1111111111111 @outter# inner=outter(home) #home=inner def home(name): time.sleep(1) print('welcome to %s page'%name) res2=index() print(res2) home('wx')