[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参数。

原文地址:https://www.cnblogs.com/wildkid1024/p/13218592.html