一,装饰器
装饰器:本质就是函数,功能是为其它的函数动态添加附加的功能
原则:对修改关闭对扩展开放
1.不修改被修饰函数的源代码
2.不修改被修改函数的调用方式
装饰器实现的知识储备:高阶函数,函数嵌套,函数闭包
## 高阶函数
# 高阶函数的定义:
1:函数接收的参数是一个参数名
2:函数的返回值是一个函数名
3:满足上述的任意一个条件,都可以称为高阶函数
一,函数接收的参数是一个参数名
def order(): print("我是函数order") def test(func): print(func) # <function order at 0x000002AD351AD378> func() # 我是函数order test(order) # 函数的实参是一个函数名,所以接收的参数是一个函数名
二,函数的返回值是一个参数名
# 下方程序不合格,函数会重复执行两次(order函数执行两次) import time def order(): time.sleep(4) print("我是函数order") def test(func): start_time = time.time() func() # 我是函数order stop_time = time.time() print("函数 %s 的执行是将为%s " %(func,(stop_time - start_time))) return func # 返回值为函数名 test_order = test(order) test_order() # 相当于执行函数 order # 输出结果 我是函数order 函数 <function order at 0x0000029DBEA298C8> 的执行是将为4.035168170928955 我是函数order
## 函数嵌套
## 函数闭包
## 装饰器的架子
def timmer(func): def wrapper(): print(func) func() return wrapper
# 下方的程序解决了重复执行函数问题
# 下方程序的问题是:对所要计算执行时间的函数都得加上 test = timmer(test)
import time def timmer(func): def wrapper(): start_time = time.time() func() # 运行的为test函数 stop_time = time.time() print("程序运行的时间%s"%(start_time-stop_time)) return wrapper def test(): time.sleep(3) print("test函数执行完毕") test = timmer(test) # 返回函数wrapper地址 test() # 执行的时wrapper # 结果 test函数执行完毕 程序运行的时间-3.000077962875366
## 语法糖
# @timmer 相当于 test = timmer(test)
# 当哪个函数需要加上装饰器,则在函数的上方加上@xxxx 语法糖
import time def timmer(func): def wrapper(): start_time = time.time() func() # 运行的为test函数 stop_time = time.time() print("程序运行的时间%s"%(start_time-stop_time)) return wrapper @timmer def test(): time.sleep(3) print("test函数执行完毕") test() # 执行的是wrapper
# 当被装饰的函数的参数变化时,装饰器的参数也得变化
import time def timmer(func): def wrapper(name,age): start_time = time.time() func(name,age) # 运行的为test函数 stop_time = time.time() print("程序运行的时间%s"%(start_time-stop_time)) print(name,age) return wrapper @timmer def test(name,age): time.sleep(3) print("test函数执行完毕") test("henry",18) @timmer def test2(name,age,addr): time.sleep(3) print("test2函数执行完毕") test2("heihei","16","China") # 程序报错:当被装饰的函数有三个实参时,装饰器中也得有对应的形参
# 使用 *args,**kwargs解决,当被装饰的函数的参数变化时,装饰器的参数也得变化的问题
import time def timmer(func): def wrapper(*args,**kwargs): start_time = time.time() func(*args,**kwargs) # 运行的为test函数 stop_time = time.time() print("程序运行的时间%s"%(start_time-stop_time)) print(*args,**kwargs) return wrapper @timmer def test(name,age): time.sleep(3) print("test函数执行完毕") test("henry",18) @timmer def test2(name,age,addr): time.sleep(3) print("test2函数执行完毕") test2("heihei","16","China") # 程序不在报错 # 输出 test函数执行完毕 程序运行的时间-3.000153064727783 henry 18 test2函数执行完毕 程序运行的时间-3.0007944107055664 heihei 16 China
## 浅浅了解*args与**kwargs
*args:将多个实参放入一个元组中,可以传多个参数
**kwargs:按照关键字传值,将多余的值以字典的形式传递
## *agrs
## 将实参与形参对应的按位置传值,多出来的给grgs # 示例1 def test(a,*args): print(a) print(args) test(1,2,3,4,5,6,7) # 输出 1 (2, 3, 4, 5, 6, 7) -------------------------------------------------------------- # 示例2(位置参数,默认参数,*args) def test(a,b = 1 ,*args): print(a) print(b) print(args) test(1,2,3,4,5,6,7) # 1给了a,b=1的值被重置为2,其余的给了args # 输出 1 2 (3, 4, 5, 6, 7) ------------------------------------------------------------- # 示例3(位置参数,*args,默认参数) def test(a,*args,b = 1 ): print(a) print(b) print(args) test(1,2,3,4,5,6,7) # 输出 1 1 (2, 3, 4, 5, 6, 7)
## **kwargs(形参中按关键字传值,多余的以自定的形式传递)
# 示例1 将所有的值给了args def test(*args,**kwargs): print(args) print(kwargs) test(1,2,3,4,5) # 输出 (1, 2, 3, 4, 5) {} --------------------------------------------------------- # 示例2 def test1(a,**kwargs): print(a) print(kwargs) test1(1,b=2,c=3,d=4) # 输出 将1给了a,将其余的以字典的形式给了Kwargs 1 {'b': 2, 'c': 3, 'd': 4} ------------------------------------------------------- # 示例3 def test3(a,*args,**kwargs): print(a) print(args) print(kwargs) test3(1,2,3,4,5,b=6,c=7) # 输出 1 (2, 3, 4, 5) {'b': 6, 'c': 7} ----------------------------------------------------- # 错误示例 def test4(z,**kwargs,*args): print(z) print(kwargs) print(args) test4(1,y=2,3,4,5) # 报错 SyntaxError: invalid syntax
小小补充:
num_l = [1,2,3,4,5,6,7,8] a,*b,c = num_l print(a) print(b) print(c) # 输出 1 [2, 3, 4, 5, 6, 7] 8 注: 普通调换两个数 a = 1 b = 2 c = a a = b b = a Python中的一一对应 a,b = b,a
## 携带参数的装饰器
import time def timmer_test(file_type="aaa"): def timmer(func): def wrapper(*args,**kwargs): if file_type == "aaa":# 执行不同的功能 print("携带的参数为aaa") elif file_type == "bbb": print("携带的参数为bbb") start_time = time.time() res = func(*args,**kwargs) # 运行的为test函数 stop_time = time.time() print("程序运行的时间%s"%(start_time-stop_time)) return res return wrapper return timmer @timmer_test(file_type="aaa") # timmer = timmer_test(file_type="aaa") 最终的结果还是@timmer,已经附加一个file_type def test1(): time.sleep(3) print("test函数执行完毕") @timmer_test(file_type="bbb") # 携带不同的参数 执行不同的功能 def test2(): time.sleep(2) print("test函数执行完毕") test1() test2() # 输出 携带的参数为aaa test函数执行完毕 程序运行的时间-3.0003297328948975 携带的参数为bbb test函数执行完毕 程序运行的时间-2.00068998336792