装饰器学习
一、装饰器
1、什么是装饰器
装饰器本质就是函数,是为其他函数添加附加功能;
2、装饰器原则
a、不修改被装饰函数的源代码;
b、不修改被装饰函数的调用方式;
c、不能违反开放封闭原则:程序一旦上线,不能更改内部源代码,一旦更改程序内部源代码,就可能产生问题;
3、装饰器的知识储备
装饰器=高阶函数+函数嵌套+闭包
(1)、高阶函数定义
a、函数接收的参数是一个函数
b、函数的返回值是一个函数;
c、满足上面条件中的任意条件都可称之为高阶函数;
#!/usr/bin/env python # _*_ coding:utf-8 _*_ #使用高阶函数为函数foo添加一个统计运行时间的功能; ##功能已经实现,没有违反修改程序源代码,没有违反函数调用方式; #但是从运行结果来看,程序运行了两遍,该方法不行; import time def foo(): time.sleep(3) print("来自foo函数") def timer(func): start_time = time.time() func() end_time = time.time() print("函数%s的的运行时间为:%s" %(func,end_time-start_time)) return func foo = timer(foo) foo() """ 来自foo函数 函数<function foo at 0x0000022DDB7729D8>的的运行时间为:3.008920431137085 来自foo函数 """
(2)、函数嵌套
函数内部调用函数不表函数嵌套,函数内部重新定义了一个函数叫函数嵌套;
#!/usr/bin/env python # _*_ coding:utf-8 _*_ ###这不是函数嵌套 import time def foo(): time.sleep(3) def bar(): print("来自bar函数") foo() print("当前时间为:%s" %time.time()) bar()
上面的函数不是函数嵌套
#!/usr/bin/env python # _*_ coding:utf-8 _*_ import time def bar(): print("来自bar函数") def foo(): time.sleep(3) print("当前时间为:%s" %time.time()) bar()
这才是函数嵌套
(3)、函数闭包
#!/usr/bin/env python # _*_ coding:utf-8 _*_ def father(name): print("来自father函数") def son(): print("我的爸爸是%s" %name) def grandson(): name = "就是我自己" print("我的爷爷是%s" %name) grandson() son() father("尼古拉斯赵四")
函数闭包其实函数作用域
#!/usr/bin/env python # _*_ coding:utf-8 _*_ import time def test(): time.sleep(3) print("test函数运行完毕") def timer(func): def wrapper(): start_time = time.time() func() end_time = time.time() print("函数func的运行时间为:%s" %(end_time-start_time)) return wrapper test = timer(test) test() """输出结果: test函数运行完毕 函数func的运行时间为:3.02397084236145 """ #备注:a、没有修改程序内部代码;b、没有修改程序的调用方式; #完成了为程序添加附加功能
4、语法糖
#!/usr/bin/env python # _*_ coding:utf-8 _*_ import time ##装饰器 def timer(func): def wrapper(): start_time = time.time() func() end_time = time.time() print("函数func的运行时间为:%s" %(end_time-start_time)) return wrapper #原函数 @timer #函数优化:语法糖@timer= test = timer(test),在原函数前面加上@timer def test(): time.sleep(3) print("test函数运行完毕") test()
函数再次优化,获取test函数的返回值
#!/usr/bin/env python # _*_ coding:utf-8 _*_ import time ##装饰器 def timer(func): def wrapper(): start_time = time.time() ###获取test函数的返回值 res = func() end_time = time.time() print("函数func的运行时间为:%s" %(end_time-start_time)) return res return wrapper #原函数 @timer #函数优化:语法糖@timer= test = timer(test),在原函数前面加上@timer def test(): time.sleep(3) print("test函数运行完毕") return "这是来自test函数的运行结果" res = test() ##此时test()就是在运行wrapper函数 print(res)
(1)、装饰器修改多个带参的函数
#!/usr/bin/env python # _*_ coding:utf-8 _*_ import time ##装饰器 def timer(func): def wrapper(*args,**kwargs): start_time = time.time() ###获取test函数的返回值 res = func(*args,**kwargs) end_time = time.time() print("函数%s的运行时间为:%s" %(func,end_time-start_time)) return res return wrapper ###当装饰器修饰带参的函数且为多个函数时,由于每个被修饰的函数的 ###形参个数不同,为了使装饰器接收任意长度的参数,故将装饰器函数的 ###参数写为可以接收任意长度,任意类型的形参 #原函数 @timer #函数优化:语法糖@timer= test = timer(test),在原函数前面加上@timer ####优化原函数为带参的参数 def test(name,age,gender): time.sleep(3) print("test函数运行完毕") return "这是来自test函数的运行结果" @timer def test1(name,age,gender,addr): time.sleep(3) print("test1函数运行完毕") return "这是来自test1函数的运行结果" res = test("尼古拉斯赵四",19,"male") ##此时test()就是在运行wrapper函数 print(res) res1 = test1("尼古拉斯赵四",19,"male","重庆市") print(res1)
(2)、解压序列:这种方法非常有用,可以快速地取到最大值和最小值
#!/usr/bin/env python # _*_ coding:utf-8 _*_ #解压序列 l = (1,2,3) a,b,c =l print(a,b,c) #1 2 3 #使用解压序列进行取值:去掉最高分和去掉最低分 l = [10,2,4,5,6,7,8,9,9,4] #升序排列 l.sort() #这种解压序列可以很快就取到第一位和最后一位; #*_表示中间的所有值 a,*_,b = l print("最低分为:%s,最高分为:%s" %(a,b)) #print("最低分为:%s,最高分为:%s" %(a,b)) print(*_) #4 4 5 6 7 8 9 9
(3)、补充:两变量值互相交换
#!/usr/bin/env python # _*_ coding:utf-8 _*_ a = 1 b = 2 x = a a = b b = x print(a,b) f1 = 1 f2 = 2 f1,f2 = f2,f1 print(f1,f2)
(4)、为函数加上验证功能:
#!/usr/bin/env python # _*_ coding:utf-8 _*_ import time def timer(func): def identer(*args,**kwargs): while True: name = input("请输入用户名:") password = input("请输入密码:") if name == "zhangsan@163.com" and password == "zhangsan": print("欢迎登陆:%s,登陆时间为:%s" %(name,time.time())) start_time = time.time() res = func(*args, **kwargs) end_time = time.time() print("函数%s运行时间为:%s" % (func, end_time - start_time)) return res break else: print("用户名或者密码输入错误,请重新输入!!!!!") return identer @timer #原函数加上验证功能 def index(): pass @timer def home(): pass @timer def shopping_cat(): pass @timer def order(): pass res = home() print(res)