python的装饰器是python的重要特性之一,通过装饰器你能够在执行已有的操作的同时,去执行额外的操作。装饰器的主要作用在不改变原有函数或者类等内部的实现的前提下,对其进行功能的拓展。这是装饰器最大的特性。

今天我们主要说明的是python装饰器实现的一些细节。

1.首先是装饰器的构成以及使用。

python的装饰器实际上是闭包的一种实现。一般的装饰器通过两层函数即可实现,形式类似于下面这样。

def outer(func_name):#fun_name是一个参数,一般是函数对象

def innert(*args,**kwargs):#*args,**kwargs是 func_name这个函数执行被传入的参数

#而外的操作
something
res = func_name(*args,**kwargs)
do_something
return res
return inner

2.说明

上面就是装饰器的一般形式,主要说明的是func_name不仅仅只有函数一种,也可以是类,也可以是类的方法,主要看使用的方式。而装饰器的使用方式也很简单,只需要使用

@decorater_name

其中decorater_name为装饰器名

3.使用

代码如下:

def timethis(func):
# @wraps(func)
def wrapper(*args,**kwargs):
start = time.time()
res = func(*args,**kwargs)
end = time.time()
dis = end - start
print("运行时长",dis)
return res
return wrapper
@timethis
def countDown(n):
while n > 0:
n -= 1

上面的代码是一个完整的装饰器的例子,其中timethis是我们定义的装饰器的名字,使用时只需将它放在所需要拓展的函数上即可。

4.待参数的装饰器

其实装饰器除了上面的这种用法外,还可以写待参数,格式如下

def decorator(*dec_args,**dec_kwargs):
def outer(func_name):
def inner(*args,**kwargs):
do_something
res = func(*args,**kwargs)
do_something
return res
return inner
return outer

上面就是写待参数的装饰器的形式,最外层函数是装饰器的名称·加上装饰器携带的参数,outer函数的参数为函数或者类对象,inner函数携带的参数为函数运行所需要i的参数。其使用的方式如下:

def timethis(name="hahah"):
# @wraps(func)
def outer(func):
print(name)
def wrapper(*args,**kwargs):
start = time.time()
res = func(*args,**kwargs)
end = time.time()
dis = end - start
print("运行时长",dis)
return res
return wrapper
return outer
@timethis("heheh")
def countDown(n):
while n > 0:
n -= 1

可以看出携带参数的装饰器的用法只需要像函数调用一样即可。

5.实例运用

下面是运行实例

heheh

运行时长 0.05710577964782715

但是以上函数在使用装饰器运行时,它的一些属性就会丢失。

countDown.__name__#针对3中的代码
'wrapper'

输出函数的名字却不是函数的名字,而这也是今天解决的重点。

6.wraps函数

wraps函数是为了解决函数使用装饰器修饰时丢失本身的一些属性而出现的,其使用的代码如下

countDown.__name__
'countDown'

从中可以看出函数名为原函数的名字,对于函数的其他属性也同样如此,这就是wraps的作用。