闭包函数:
- 1.闭:定义在函数内部的函数
- 2.包:内部函数引用了外部函数作用域的名字
def outter(): x = 1 def inner() print(x) # 这一步引用 x = 1 return inner res = outter() res() # 1 def func() x = 2 res() # 这里相当于 res(outter()),而res()的调用结果为1 func() # 1 ,这里调用func函数,执行内部函数代码,虽然x = 2存在,但是执行res()后,又执行了一次x = 1赋值,所以结果返回1
- 给函数体传值的第一种方式:传参
def index(username): print(username)
- 给函数体传值的第二种方式:闭包
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def outter() x = 1 y = 2 def my_max(): if x > y: return x return y return my_max res = outter() # res 就是my_max函数的内存地址 res() # my_max函数的内存地址 print(res()) #结果为x,y中的最大值
或者
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def outter(x,y) def my_max(): if x > y: return x return y return my_max res = outter(1,2) # res 就是my_max函数的内存地址 res() # my_max函数的内存地址 print(res()) # x,y中的最大值
Pycharm解释器知识点: pip3 install requests装requests模块
- 函数传参的第一种方式:直接给函数传参
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import requests # 导入requests模块 def my_get(url): response = requests.get(url) if response.status_code == 200: print(len(response.text)) my_get('此处输入网址')
- 函数传参的第二种方式:*闭包*
import requests def outer() url = '网址' def my_get(): response = requests.get(url) if response.status_code == 200: print(len(response.text)) return my_get() my_jd = outter('此处输入网址') my_jd() # 相当于my_jd(outter()) my_baidu = outter('此处输入网址') my_baidu() # 相当于my_baidu(outter())
装饰器:
装饰器:用工具给被装饰对象添加新的功能
开放封闭原则:
- 开放:对扩张开放 (你扩展没事,别减少代码)
- 封闭:对修改封闭 (不被允许修改原代码被修饰函数代码)
装饰器必须遵循的两个原则:
- 1.不改变被装饰对象源代码
- 2.不改变被装饰对象(可调用对象)的调用方式
def index(): pass index() # 上面定义的index函数,你就老老实实的用常规方式调用index()函数
关于如何使用?
- 1.统计index函数执行时间
import time print(time.time(3)) # 1562812014.731474 时间戳,当前时间距离1970-1-1 00:00:00相差的秒数 def index(): print('XXXXXX') time.sleep(3) # 此处是让cpu睡3秒 print('XXXXX') # 这是返回输出XXXXX所执行的时间
- 2.下面是常规的用start和end来记录当前时间:
import time def index(): time.sleep(3) print('XXXXXX') strat = time.time() index() end = time.time() print('index run time:%s'%(end-start)) # 返回的是index函数从开始到结束的运行时间差
- 3.下面是初步装饰函数:
import time def index(): time.sleep(3) print('XXXXXX') def get_time(func) # func=index函数 strat = time.time() func() # func=index函数内存地址() end = time.time() print('index run time:%s'%(end-start)) get_time(index)
装饰器简单版本:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time def index(): time.sleep(3) print('XXXXXX') def outter(func): def get_time(): start = time.time() func() end = time.time() print('index run time:%s' % (end - start)) return get_time res = outter(index) res()
装饰器进化版本:
如果我们要统计login执行时间:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time def index(): time.sleep(3) print('XXXXXX') def login(name): time.sleep(1) print('%s is sb'%name) def outter(func): # func = 最开始的login函数的内存地址 def get_time(*args,**kwargs): # args = ('egon',) kwargs = {} strat = time.time() func(*args,**kwargs) # func=最开始的login函数内存地址() 直接调用 end = time.time() print('index run time:%s'%(end-start)) return get_time login = outter(login) # outer(最开始的login函数内存地址) login('egon')
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time def index(): time.sleep(3) print('XXXXXX') def login(name): time.sleep(1) print('%s is sb'%name) def outter(func): # func = 最开始的login函数的内存地址 def get_time(*args,**kwargs): # args = ('egon',) kwargs = {} strat = time.time() res = func(*args,**kwargs) # func=最开始的login函数内存地址() 直接调用 return res end = time.time() print('index run time:%s'%(end-start)) return get_time login = outter(login) # outer(最开始的login函数内存地址) res = login('egon') login('egon')
''''''
函数参数的问题:无参函数和有参函数是否都可以直接调用
函数可以接收任意数量的参数
语法糖在书写时应该与被装饰对象紧挨着,两者之间不要有空格
''''''
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def outter(func): def get_time(*args,**kwargs): strat = time.time() func(*args,**kwargs) return res end = time.time() print('index run time:%s'%(end-start)) return get_time @outter # login = outer(index) def index(): time.sleep(3) print('XXXXXX') @outter # login = outer(login) def login(name): time.sleep(1) print('%s is sb'%name)
装饰器模板:
def outter(func):
def inner(*args,**kwargs):
print('执行被装饰函数之前,你可以做的操作')
res = func(*args,**kwargs)
print('执行被装饰函数之后,你可以做的操作')
return res
return inner
认证装饰器:
执行函数index之前必须先输入用户名和密码,正确之后才能执行index;否则提示用户输入错误,结束程序
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time user_dic = {'is_login':None} def login_auth(func): # 其实就是func = index def inner(*args,**kwargs): if user_dic['is_login']: res = func(*args,**kwargs) return res else: username = input('请输入用户名:').strip() password = input('请输入密码:').strip() if username == 'jason' and password == '123': user_dic['is_login'] = True res = func(*args,**kwargs) return res else: print('用户名或者密码错误') return inner @login_auth def index(name): time.sleep(1) print('%s is dsb'%name)
多层装饰器:(重要)
装饰器在装饰的时候,顺序是从下往上
装饰器在执行的时候,顺序是从上往下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time def outter(func): def get_time(*args,**kwargs): strat = time.time() res = func(*args,**kwargs) return res end = time.time() print('index run time:%s'%(end-start)) return get_time def login_auth(func): # 其实就是func = index def inner(*args,**kwargs): # 这里的参数是跟被装饰函数的参数一一对应的 if user_dic['is_login']: res = func(*args,**kwargs) return res else: username = input('请输入用户名:').strip() password = input('请输入密码:').strip() if username == 'jason' and password == '123': user_dic['is_login'] = True res = func(*args,**kwargs) return res else: print('用户名或者密码错误') return inner @login_auth # index = login_auth(get_time) index = inner函数的内存地址 @outter # get_time = outter(index) index是最开始的index def index(name): time.sleep(1) print('%s is dsb'%name)
三层装饰器:(重要)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def login_auth2(data_source) def login_auth(func): # 其实就是func = index def inner(*args,**kwargs): # 这里的参数是跟被装饰函数的参数一一对应的 if user_dic['is_login']: res = func(*args,**kwargs) return res else: if data_source == 'file': username = input('请输入用户名:').strip() password = input('请输入密码:').strip() if username == 'jason' and password == '123': user_dic['is_login'] = True res = func(*args,**kwargs) return res else: print('用户名或者密码错误') elif data_source == 'MYSQL': print('form MYSQL') elif data_source == 'ldsp': print('from ldsp') else: print('暂时无数据来源') return inner @login_auth2(data_source,x,t) # login_auth2(data_source,x,t)等价于login_auth,data_source = 'file' @outter # get_time = outter(index) index是最开始的index def index(name): time.sleep(1) print('%s is dsb'%name)
装饰器补充:
我们用装饰器的最终目标就是:
- 用户查看被装饰函数的函数名的时候,查看到的就是被装饰函数本身
- 用户查看被装饰函数的注释的时候,查看到的就是被装饰函数的注释
方法就是下面这两句代码:
form functools import wraps
@wraps(func) '''装饰器修复技术'''
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
form functools import wraps def outter(func): @wraps(func) # 装饰器修复技术 def inner(*args,**kwargs): print('执行被装饰函数之前,你可以做的操作') res = func(*args,**kwargs) print('执行被装饰函数之后,你可以做的操作') return res return inner @outter # outter(最原始的index内存地址) def index(): ''' 这是index函数 :return ''' print(index) print(help(index)) # 查看函数的注释 print(index.name) # 查看函数名字字符串形式