闭包函数和装饰器
一、闭包函数
1.什么是闭包
定义在函数内部的函数
内部函数引用了外部函数名称空间作用域的名字
2.给函数传参的两种方式:
(1)直接传参
def index1(username): print(username)
(2)闭包
def outter(name): # name = 'jason' def index(): print(name) return index
3.作用领域:延迟计算
from urllib.request import urlopen def index(url): def get(): return urlopen(url).read() return get baidu=index('http://www.baidu.com') print(baidu().decode('utf-8'))
二、装饰器
1.什么是装饰器
给被装饰的对象添加功能的工具,本身是可调用对象
2.遵循的两个原则:
(1)不修改被装饰对象的源代码
(2)不修改被装饰对象的调用方式
3.为什么要用装饰器
开放封闭原则:对修改封闭,对扩展开放
4.装饰器的使用
时间戳的使用
import time print(time.time()) # 1562812014.731474 时间戳 当前时间距离1970-1-1 00:00:00相差的秒数 # 1970-1-1 00:00:00是Unix诞生元年
延迟程序运行时间
import time time.sleep(3) # 让cpu谁三秒 让你的程序暂停三秒 print('FBI warning!')
统计index函数执行的时间
import time def index(): time.sleep(3) print('欢迎你') start = time.time() # 记录程序开始时间 index() end = time.time() # 记录程序结束时间 print('index run time:%s'%(end-start)) # 打印程序运行时间
import time def index(): time.sleep(3) print('欢迎你') def outter(func): # func = 最原始的index函数的内存地址 def get_time(): start = time.time() func() # func = index函数的内存地址() 直接调用 end = time.time() print('index run time:%s'%(end-start)) return get_time index = outter(index) # outter(最原始的index函数内存地址) # index指向get_time函数的内存地址 index()
进阶版(函数可以接收任意数量的参数)
import time def index(): time.sleep(3) print('欢迎你') return 'index' def login(name): time.sleep(1) print('%s is sb'%name) return 'login' def outter(func): # func = 最原始的login函数的内存地址 def get_time(*args, **kwargs): # args = ('egon',) kwargs = {} start = time.time() res = func(*args, **kwargs) # 最原始的login函数的内存地址() 直接调用 func('egon') end = time.time() print('func run time:%s'%(end-start)) return res return get_time login = outter(login) # outter(最原始的login函数的内存地址) res = login('egon') print(res) # 返回值 login index = outter(index) res1 = index() print(res1) # 返回值 index
5.装饰器语法糖
@装饰器外部的函数名
语法糖在书写的时候应该与被装饰对象紧紧挨着
两者之间不要有空格
import time def outter(func): # func = 最原始的login函数的内存地址 def get_time(*args, **kwargs): # args = ('egon',) kwargs = {} start = time.time() res = func(*args, **kwargs) # 最原始的login函数的内存地址() 直接调用 func('egon') end = time.time() print('func run time:%s'%(end-start)) return res return get_time @outter # index = outter(index) outter(最原始的index的函数的内存地址) def index(): time.sleep(3) print('欢迎你') return 'index' @outter # login = outter(login) def login(name): time.sleep(1) print('%s is sb'%name) return 'login' @outter # home = outter(home) def home(*args,**kwargs): time.sleep(1) return 'home' index() login('egon') home()
6.无参装饰器
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)
7.有参装饰器
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
8.装饰器模板
def outter(func): def inner(*args,**kwargs): print("执行被装饰函数之前的操作") res = func(*args,**kwargs) # 最原始函数的内存地址() 直接调用 print("执行被装饰函数之后的操作") return res # 返回最原始函数的内存地址() return inner
认证装饰器
执行函数index之前必须先输入用户名和密码,正确之后才能执行index,否则提示用户输入错误 结束程序
import time user_dic = {'is_login':None} def login_auth(func): def inner(*args,**kwargs): if user_dic['is_login']: res = func(*args,**kwargs) return res else: name = input("请输入用户名:") pwd = input("请输入密码:") if name == 'ylj' and pwd == '123': user_dic['is_login'] = True res = func(*args,**kwargs) print(res) return res else: print("用户名或者密码错误!") return inner @login_auth def index(name): time.sleep(3) print("欢迎你%s" %name) return index index('ylj') print(index)
9.多层装饰器
装饰器在装饰的时候,顺序从下往上,类似于将产品包装
装饰器在执行的时候,顺序从上往下,类似于将包装的产品拆开
def outter1(func1): #func1=wrapper2的内存地址 print('加载了outter1') def wrapper1(*args,**kwargs): print('执行了wrapper1') res1=func1(*args,**kwargs) print('结束了wrapper1') return res1 return wrapper1 def outter2(func2): #func2=wrapper3的内存地址 print('加载了outter2') def wrapper2(*args,**kwargs): print('执行了wrapper2') res2=func2(*args,**kwargs) print('结束了wrapper2') return res2 return wrapper2 def outter3(func3): # func3=最原始的那个index的内存地址 print('加载了outter3') def wrapper3(*args,**kwargs): print('执行了wrapper3') res3=func3(*args,**kwargs) print('结束了wrapper3') return res3 return wrapper3 @outter1 # index = outter1(wrapper2) @outter2 # wrapper2 = outter2(wrapper3) @outter3 # wrapper3 = outter3(index) def index(): print('from index') index()
8.装饰器修复技术
用户查看被装饰函数的函数名的时候查看到的就是被装饰函数本身
用户查看被装饰函数的注释的时候查看到的就是被装饰函数的注释
from functools import wraps
@wrps()
from functools import wraps def outter(func): @wraps(func) # 装饰器修复技术 def inner(*args,**kwargs): """ 我是inner函数 :param args: :param kwargs: :return: """ print('执行被装饰函数之前 你可以执行的操作') res = func(*args,**kwargs) print('执行被装饰函数之后 你可以执行的操作') return res return inner @outter # index = outter(最原始的index内存地址) def index(): """ 这是index函数 :return: """ pass
ps:
print(help(index)) 查看函数的注释
print(index._name_) 查看函数名字字符串形式

浙公网安备 33010602011771号