1.什么是python的装饰器
通俗点说,装饰器就是一个返回值是函数的函数,这么说可能有点绕。
仔细分解:
1.首先它是函数
2.它的返回值是一个函数
2.装饰器的作用
装饰器是一个返回函数的函数(默读三十遍 _ ),那么它的作用是什么呢?还是一句话描述的话:用于增强其他已存在函数的功能!目的是在不改变原函数名(类名)的情况下,给函数增加新的功能。
3.代码解释装饰器
先来点前奏:正常情况下当我们想要拓展原来的函数功能时,最直接的方式就是改动函数(以前我也这么想),但是现实却不是这样的,人家函数辛辛苦苦写的好好的,你去改它万一出问题了谁能负责呢?所以这是万万不能改滴。因此,这也就出现了装饰器,上菜:
# 函数fun1如下所示,现在我们想要看一下这个函数执行的总时间(不能改动这个代码)
def fun1(num1,num2):
time.sleep(10)
print(num1+num2)
# 既然不能改动这个函数,那么只能自己再定义个函数咯
def deco(func): # 这个func其实就是一个函数,如果我们在fun1函数上加@deco这个装饰器,这个func就是fun1
def wrapper():
start_time = time.time()
func() # 这里就是调用了func方法
end_time = time.time()
execution_time = end_time - start_time
print(execution_time)
return wrapper
像上面这样,deco就是一个装饰器,fun1就是一个函数。
当我们在fun1函数上面加上deco这个装饰器的话,就意味着将fun1传递给deco这个装饰器。
实际上就是在调用fun1这个方法时就是调用了deco(fun1)这个函数,也就是fun1 = deco(fun1)了
# 加上装饰器的函数
@deco
def fun1(num1,num2):
time.sleep(10)
print(num1+num2)
# 装饰器
def deco(func): # 这个func其实就是一个函数,如果我们在fun1函数上加@deco这个装饰器,这个func就是fun1
def wrapper():
start_time = time.time()
func() # 这里就是调用了func方法
end_time = time.time()
execution_time = end_time - start_time
print(execution_time)
return wrapper
所以当我们在调用fun1这个函数的时候,其实就是调用了deco(fun1)这个函数
执行fun1() 就等于执行 deco(fun1)()
因为deco(fun1)返回的是wrapper方法,所以 deco(fun1)()就是执行wrapper方法。
那么,当有两个装饰器装饰一个函数的时候是什么情况呢?
def deco01(f):
def wrapper(*args, **kwargs):
print("this is deco01")
start_time = time.time()
f(*args, **kwargs)
end_time = time.time()
execution_time = (end_time - start_time)*1000
print("time is %d ms" % execution_time)
print("deco01 end here")
return wrapper
def deco02(f):
def wrapper(*args, **kwargs):
print("this is deco02")
f(*args, **kwargs)
print("deco02 end here")
return wrapper
@deco01
@deco02
def f(a,b):
print("be on")
time.sleep(1)
print("result is %d" %(a+b))
# this is deco01
# this is deco02
# be on
# result is 7
# deco02 end here
# time is 1000 ms
# deco01 end here
# 对于Python中的”@”语法糖,装饰器的调用顺序与使用 @ 语法糖声明的顺序相反。
# 在这个例子中,”f(3, 4) = deco01(deco02(f(3, 4)))”。
# 先执行deco1,再执行deco2,deco2在deco1里面执行
4.python内置装饰器
python内置有三个装饰器,分别是@property,@staticmethod,@classmethod都是和class有关
其作用:
@property:将某函数,作为属性使用
class Animal():
@property
def fun1(self):
return self.value
@fun1.setter
def fun1(self,value):
self.value = value
@property
def fun2(self):
print("nihao")
if __name__=="__main__":
Animal.fun1 = 9 # 这里相当于是给value赋值了,调用了@fun1.setter函数
print Animal.fun1 # 调用@property函数
Animal.fun2
#总结:就是将方法当作一个属性来使用,并且可以赋值
@classmethod:类方法,直接通过类名.方法名进行调用
class A():
@classmethod
def fun1(cls,x,y):
return x*y
def fun2(self,x,y):
return x*y
if __name__="__main__":
print A.func1(1,2) # 直接调用,不要实例化对象
print A().fun2(1,2)
@staticmethod 静态,将方法静态化,直接可以用类.方法来调用
class A():
@staticmethod
def fun1(x,y):
return x*y
def fun2(self,x,y):
return x*y
if __name__="__main__":
print A.func1(1,2) # 直接调用,不要实例化对象
print A().fun2(1,2)
装饰器的理解就是这么多,总结而言就是两句话:
1.装饰器是一个返回值是函数的函数
2.装饰器的目的是为了给已存在的函数增强功能