闭包函数
闭包函数的定义:
闭:定义在函数内部的函数
包:内部函数引用了外部函数作用域的名字
给函数体传值的两种方式:
1.传参
def index1(username):
print(username)
2.闭包
def outter(x,y): #在函数内传参,在res1中调用,相当于x=1,y=40 # x = 1 # y = 40 def my_max(): if x > y: return x return y return my_max res1 = outter(1,40) # res就是my_max函数的内存地址 print(res1()) #这里打印的还是1和40,想结束不让他打印1和40的话只能结束程序或者再传其他参数 print(res1()) print(res1()) res2 = outter(90,200) print(res2()) print(res2())
import requests def outter(url): #给函数传参,在my_jd中定义实参传给形参 # url = 'https://www.jd.com' #固定传参 def my_get(): response = requests.get(url) if response.status_code == 200: print(len(response.text)) return my_get my_jd = outter('https://www.jd.com') #my_jd接收的是my_get的内存地址 my_jd() my_jd() my_baidu = outter('https://www.baidu.com') my_baidu() my_baidu() my_baidu() my_baidu() my_baidu()
装饰器
装饰器:
器:就是一个工具
装饰:给被装饰对象添加新的功能
为什么要用装饰器?
开放封闭原则:
开放:对扩展开放
封闭:对修改开放
装饰器(可调用对象)必须遵循的两个原则:
1.不改变被装饰对象的源代码
2.不改变被装饰对象(可调用对象)调用方式
首先写一个time模块的示例
import time def index(): time.sleep(3) # 让CPU睡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' res1 = index() def login(name): #有参函数 time.sleep(1) print('%s is s'%name) return 'login' res = login('zhangsan') def outter(func): # func = 最原始的login函数的内存地址 def get_time(*args, **kwargs): # 写*args和**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)
语法糖
def outter(func): # func = 最原始的index函数的内存地址 def get_time(*args, **kwargs): start = time.time() res = func(*args, **kwargs) # 最原始的index函数的内存地址() 直接调用 end = time.time() print('func run time:%s'%(end-start)) return res return get_time @outter # 语法糖,等同于index = outter(index),outter会直接把离他最近的一个函数名当做自己的参数传入 def index(): time.sleep(3) print('开业啦') return 'index'
装饰器模板
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): # func = index def inner(*args,**kwargs): if user_dic['is_login']: # 如果用户已经在登录状态 res = func(*args, **kwargs) return res #直接将参数返回 else: username = input('please input your username>>>:').strip() password = input('please input your password>>>:').strip() if username == 'wu' and password == '123': user_dic['is_login'] = True res = func(*args,**kwargs) return res else: print('username or password error') return inner
装饰器补充 @wraps
def outter(func): @wraps(func) def inner(*args, **kwargs) print('执行被装饰函数之前,可以做的操作') res = func(*args, **kwargs) print('执行被装饰函数之后,可以做的操作') return res return inner # 用户查看被装饰函数的函数名的时候查看到的就是被装饰函数本身 # 用户查看被装饰函数的注释的时候查看到的就是被装饰函数的注释