闭包函数,函数装饰器,语法糖
一.闭包函数:
闭包函数:
闭:定义在函数内部的函数
包:内部的函数引用了外部函数作用域的名(变量名)
闭包也是一种传参方式
def outter(x,y): # x = 1 # y = 2 def my_max(): if x > y: return x return y return my_max res = outter(1,2) # outter加()本身会得到一个返回值my_max,实参1和2相当于变量值传给了x和y两个变量名 print(res())
import requests # 爬虫模块 #方式一 直接给函数传参 info1 = 'https://www.baidu.com' info2 = '......' def my_get(rul): resuit = requests.get(rul) if resuit.status_code == 200: print(len(resuit.text)) my_get(info1) my_get(info2) '.....' #方式二 用闭包的方式给函数传参 def outter(func): # func = 'https://www.jd.com' def my_get(func): resuit = requests.get(func) if resuit.status_code == 200: print(len(resuit.text)) return my_get res_jd = outter( 'https://www.jd.com') # res = my_get res_jd() # my_get()
二.装饰器:
装饰器
器:就是一个工具
装饰:给被装饰对象(函数)添加功能
开放封闭原则:
开放:对扩展开放
封闭:对修改封闭
装饰器(被调用对象)必须遵循的两大原则:
1.不改变装饰对象(被装饰函数)的源码
2.不改变被装饰对象的调用方式
import time print(time.time()) # 1562812014.731474 时间戳 当前时间距离1970-1-1 00:00:00相差的秒数 # 1970-1-1 00:00:00是Unix诞生元年 time.sleep(3) # 让cpu谁三秒 让你的程序暂停三秒 print('FBI!')
通用装饰器模板
def outter(func): def inner(*args,**kwargs): print('执行被装饰函数之前 你可以做的操作') res = func(*args,**kwargs) print('执行被装饰函数之后 你可以做的操作') return res return inner
def auth(driver='file'): def auth2(func): def wrapper(*args,**kwargs): name=input("user: ") pwd=input("pwd: ") if driver == 'file': if name == 'egon' and pwd == '123': print('login successful') res=func(*args,**kwargs) return res elif driver == 'ldap': print('ldap') return wrapper return auth2 @auth(driver='file') def foo(name): print(name) foo('egon') 有参装饰器
统计func函数运行时间:
# 简单版: def func(): time.sleep(2) # 让cpu睡眠2秒 print('form func') star_res = time.time() func() over_res = time.time() print('运行时间: %s'%(over_res - star_res)) # >>> 运行时间: 2.00064754486084 #此时的计算时间功能只能func函数单独使用,如果其他函数也要用到时间计算功能需要重新编写代码, # 可以把计算时间功能封装成一个函数给其他函数使用 #有装饰器版 def func(): time.sleep(2) # 让cpu睡眠2秒 print('form func') def outter(info): # info = 原始func的内存地址 def time_func(): star_res = time.time() info() # 相当于 func() 函数运行 over_res = time.time() print('运行时间: %s'%(over_res - star_res)) return time_func func = outter(func) # 新 func = time_func的内存地址 func() # 相当于 time_func()函数运行 # >>> form func # >>> 运行时间: 2.0006558895111084
import time def index(): time.sleep(3) print('澳门最大线上赌场开业啦 性感tank在线发牌!') return 'index' # res1 = index() def login(name): time.sleep(1) print('%s is sb'%name) return 'login' # res = login('egon') 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) # >>>egon is sb # >>>func run time:1.000328779220581 # >>>login index = outter(index) res1 = index() print(res1) # >>>澳门最大线上赌场开业啦 性感tank在线发牌! # >>>func run time:3.0011234283447266 # >>>index
在装饰器内,定义形参 *args ,**kwargs 可以接收有参无参函数
def func(): time.sleep(2) # 让cpu睡眠2秒 print('form func') return '函数func的返回值' def user(name): time.sleep(1) print('welcome %s'%name) return '函数user的返回值' def outter(info): # info = 原始func的内存地址 # info = 原始user的内存地址 def time_get(*args,**kwargs): # args = ' ' # kwargs = ' ' 闭包函数的特性 star_res = time.time() res = info(*args,**kwargs) # 相当于 func() 函数运行 # 相当于user()函数运行,但函数user必须要传参才能执行 over_res = time.time() print('运行时间: %s'%(over_res - star_res)) return res return time_get func = outter(func) # 新 func = time_get的内存地址 res_1 =func() # 相当于 time_get()函数运行 print(res_1) # res_1 = res = 函数func的返回值 # >>> form func # >>> 运行时间: 2.0006558895111084 # >>> 函数func的返回值 user = outter(user) # 新 user = rime_get 的内存地址 res_2 = user('wong') # 相当于 time_get()运行函数 print(res_2) # >>> welcome wong # >>> 运行时间: 1.000464677810669 # >>> 函数user的返回值
三.语法糖 @+装饰器函数名
语法糖在书写的时候应该与被装饰对象紧紧挨着
两者之间不要有空格
@+装饰器函数名 相当于它拿到了它所装饰的哪个函数的内存地址,当作实参传给装饰器的形参
import time def outter(info): # info = 原始func的内存地址 # info = 原始user的内存地址 def time_get(*args,**kwargs): # args = ' ' # kwargs = ' ' 闭包函数的特性 star_res = time.time() res = info(*args,**kwargs) # 相当于 func() 函数运行 # 相当于user()函数运行,但函数user必须要传参才能执行 over_res = time.time() print('运行时间: %s'%(over_res - star_res)) return res return time_get # func = outter(func) # 新 func = time_get的内存地址 # res_1 =func() # 相当于 time_get()函数运行 # print(res_1) @outter # func = outter(func) def func(): time.sleep(2) # 让cpu睡眠2秒 print('form func') return '函数func的返回值' func() @outter # user = outter(func) def user(name): time.sleep(1) print('welcome %s'%name) return '函数user的返回值' user('wong')
# 装饰器在装饰的时候 顺序从下往上
# 装饰器在执行的时候 顺序从上往下
def outter1(func1): #func1=wrapper2的内存地址 print('加载了outter1') def wrapper1(*args,**kwargs): print('执行了wrapper1') res1=func1(*args,**kwargs) # func1=wrapper2的内存地址 return res1 return wrapper1 def outter2(func2): #func2=wrapper3的内存地址 print('加载了outter2') def wrapper2(*args,**kwargs): print('执行了wrapper2') res2=func2(*args,**kwargs) # func2=wrapper3的内存地址 相当于wrapper3() 并执行 return res2 return wrapper2 def outter3(func3): # func3=最原始的那个index的内存地址 print('加载了outter3') def wrapper3(*args,**kwargs): print('执行了wrapper3') res3=func3(*args,**kwargs) # func3=最原始的那个index的内存地址 相当于 index() 并执行 return res3 return wrapper3 @outter1 # outter1(wrapper2的内存地址)======>index=wrapper1的内存地址 @outter2 # outter2(wrapper3的内存地址)======>wrapper2的内存地址 @outter3 # outter3(最原始的那个index的内存地址)===>wrapper3的内存地址 # wrapper = outter3(index) def index(): # func3(*args,**kwargs)的时候运行此函数 print('from index') # 最后一步 index() # 相当于 wrapper1()
详情分析链接