假如有一个函数,我需要给这个函数添加新功能,但是不改变这个函数的调用方式,那么就可以用到了装饰器
原始版
原函数
# _*_coding:utf8_*_
import time
def func1():
time.sleep(1)
print('这是函数1')
func1()
输出结果为
C:\Python\Python36\python.exe D:/Python/Demo/装饰器.py
这是函数1
如果我需要给这个函数多添加一个打印内容,那么我就可用这样做
import time
def func1():
time.sleep(1)
print('这是函数1')
def func2(f):
print('这是函数2')
return f
func1 = func2(func1) #创建一个新的func1 这个和前面的func1函数是不同的东西。是一个新的
func1() # 实现调用
输出结果为
C:\Python\Python36\python.exe D:/Python/Demo/装饰器.py
这是函数2
这是函数1
这样就实现了简单的装饰器的功能,具体实现原理就是,创建一个新的函数func2
,然后把func1
的名称空间当做参数传给func2
,然后返回func1
,没有加()也就是没有实现调用,当后面执行func1()
,就实现了调用了。
没有改变func1
的调用方式,但是运行func1
出现的结果多了内容,这就实现了一个简单的装饰器。
在python
中,func1 = func2(func1)
可用用@func2
代替,具体优化代码如下
# _*_coding:utf8_*_
import time
def func2(f):
print('这是函数2')
return f
@func2
def func1():
time.sleep(1)
print('这是函数1')
func1()
上面是最简单的只加一个功能输出,下面这个加一个函数运行时间
# _*_coding:utf8_*_
import time
def func2(f):
print('这是函数2')
def inner():
start = time.time()
f()
end = time.time()
print(end-start)
return inner
@func2
def func1():
time.sleep(1)
print('这是函数1')
func1()
运行结果为:
C:\Python\Python36\python.exe D:/Python/Demo/装饰器.py
这是函数2
这是函数1
1.000349521636963
加上返回值版本
上面的func1
没有返回值,如果func1
加上返回值,那么代码就需要改造了
# _*_coding:utf8_*_
import time
def func2(f):
print('这是函数2')
def inner():
start = time.time()
result = f()
end = time.time()
print(end-start)
return result
return inner
@func2
def func1():
time.sleep(1)
print('这是函数1')
return '这是函数1的返回值'
print(func1())
结果为
C:\Python\Python36\python.exe D:/Python/Demo/装饰器.py
这是函数2
这是函数1
1.0005292892456055
这是函数1的返回值
上面实现的过程为在inner
函数中,增加一个返回值,这个inner
的返回结果,就是第一个func1
的返回结果
加上传递参数功能
上面的代码func1
没有传递参数的功能,如果需要加上参数传递呢?
代码可用这样改写
# _*_coding:utf8_*_
import time
def func2(f):
print('这是函数2')
def inner(a): # 这里的a接收func1中的a的参数
start = time.time()
result = f(a) #这里的a执行
end = time.time()
print(end-start)
return result
return inner
@func2
def func1(a):
time.sleep(1)
print('这是函数1')
print(a)
return '这是函数1的返回值'
print(func1(1111111))
执行结果为:
C:\Python\Python36\python.exe D:/Python/Demo/装饰器.py
这是函数2
这是函数1
1111111
1.000321626663208
这是函数1的返回值
给func1
传递一个11111111
,之后打印11111111
装饰器被不同的函数调用,传递不同的参数
假如func2
需要装饰func1
和func3
,但是func1
传递一个参数,func3
传递二个参数,那么func2
只需要把接收参数修改为*args,**kwargs
即可
# _*_coding:utf8_*_
import time
def func2(f):
print('这是函数2')
def inner(*args,**kwargs):
start = time.time()
result = f(*args,**kwargs)
end = time.time()
print(end-start)
return result
return inner
@func2
def func1(a):
time.sleep(1)
print('这是函数1')
print(a)
return '这是函数1的返回值'
@func2
def func3(a,b):
time.sleep(1)
print('这是函数3')
print(a)
return '这是函数3的返回值'