[python]python进阶编程(3)-装饰器
说明
前面我们提到了闭包的概念,闭包是python的一个重要特性,而装饰器是闭包的一个重要应用。
闭包
闭包即为返回值为函数的函数。示例程序如下所示:
def num(num):
def num_in(num2):
return num + num2
return num_in #返回函数
a = num(100) # a是一个函数。
b = a(100) # 110 。
装饰器
在一些需要对已有函数进行修改但是不改变原有函数功能场景中,比如对某个函数的运行进行计时,打log等,就需要用到装饰器函数了。
无参装饰器
无参装饰器即为装饰器本身没有参数,那么其运行时也是最简单的,即为两层的闭包。以下程序示例:
def timer(fun):
def run():
t1 = time.time()
fun()
run_time = time.time() - t1
print('程序运行时间为', run_time)
return run
def funs():
time.sleep(1)
print('无参函数')
funs()
funs = timer(funs) # 使函数调用没有发生变化,但是多了统计运行时间功能
funs()
@timer # 在函数声明时加入语法糖,等同于funs = timer(funs)
def funs():
以上的过程为一个简单装饰器的使用过程,而调用过程分为有语法糖的调用,以及没有语法糖的调用。上述的示例展示了装饰无参函数的装饰器,那么如果使用有参有返回值的的装饰器应该怎么写?以下程序示例:
def timer(fun):
def run(*args, **kwargs): # 不定长参数
t1 = time.time()
out = fun(*args, **kwargs)
run_time = time.time() - t1
print('程序运行时间为', run_time)
return out
return run
def funs(a, b):
time.sleep(1)
return a + b
print(funs(3, 5))
funs = timer(funs)
print(funs(3, 5))
有参装饰器
在某些情况下,需要对装饰器传入参数,比如在统计时间时,有的程序要求统计单位为ms,有的要求为s,那么就可以通过有参的装饰器来实现:
def var_timer(ns=1000):
def timer(fun):
def run(*args, **kwargs):
t1 = time.time()
out = fun(*args, **kwargs)
run_time = time.time() - t1
print('程序运行时间为', run_time * ns)
return out
return run
return timer
@var_timer(1000) # 注意此时统计的是ms,当然也可以统计ns和s
def funs(a, b):
time.sleep(1)
return a + b
print(funs(3, 5))
内置装饰器
常见的内置装饰器有三种,@property、@staticmethod、@classmethod。
@property
把类内方法当成属性来使用,必须要有返回值,相当于getter;
假如没有定义 @func.setter 修饰方法的话,就是只读属性。
@staticmethod
静态方法,不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样,静态方法通常维护一个共同的静态量。
@classmethod
类方法,不需要self参数,但第一个参数需要是表示自身类的cls参数。