Python自学之乐-装饰器浅谈

以前学过点 面向对象的知识,我感觉这之间是有关联的,比如说装饰器的第一个要素是对被装饰的函数的封闭性,不允许更改;第二个就是对装饰器本oj身的可扩展性。

装饰器要点:高阶函数+嵌套函数=装饰器

需要掌握的知识点:1、函数即变量

2、高阶函数(函数的参数也是函数)

3、嵌套函数

装饰器一:装饰器不带参数,被装饰的函数也不带参数

简单的需求:现有两个简单的打印内容的函数,现在需要在不改变两个函数源代码的情况下统计每个函数运行时间

import time
def timer(func):#用到高阶函数
def deco():#用到函数嵌套
start_time = time.time()
func()
stop_time = time.time()
print("the func run %s" %(stop_time-start_time))
return deco
@timer
def test1():
time.sleep(3)
print("i am test1")
@timer
def test2():
time.sleep(3)
print("i am test2")
test1()
test2()
执行顺序:首先程序自上往下走,走到定义的timer函数的时候会跳到@timer处,检测到timer被作为装饰器了,系统会去搜索哪些地方使用了timer作为装饰器,搜索完成后,执行timer;紧接着执行我们调用的test1(),因为test1被timer装饰了,所以会先去执行装饰器,在装饰器内部执行到func()时,此时func()就是test1()! test2()也是一样
装饰器的效果就是:没有改变原来函数的源代码和函数调用方式,又给函数增加了新功能

装饰器二:被装饰函数带参数

上面的代码被装饰的函数都没有参数,显然功能很局限,加上两个参数我们再看一看
def timer(func):
def deco(*args,**kwargs):
start_time = time.time()
func(*args,**kwargs)
stop_time = time.time()
print("the func run %s" %(stop_time-start_time))
return deco
@timer
def test1():
time.sleep(3)
print("i am test1")
@timer
def test2(name,age):
time.sleep(3)
print("i am test2",name,age)
test1()
test2("clark",20)
执行结果:

i am test1
the func run 3.010805368423462
i am test2 clark 20
the func run 3.010805130004883

 

总结:我们看到,我们的装饰器加入了*args **kwargs参数的固定写法,无论被装饰的函数有参数(test2)或者没有参数(test1),最终都可以实现装饰效果,而且两个函数本身正常运行

 

装饰器三:被装饰函数有返回值
#Author:clark
import time
def timer(func):#用到高阶函数
def deco(*args,**kwargs):#用到函数嵌套
start_time = time.time()
val = func(*args,**kwargs)
stop_time = time.time()
print("the func run %s" %(stop_time-start_time))
return val
return deco
@timer
def test1():
time.sleep(3)
print("i am test1")
@timer
def test2(x):
time.sleep(3)
print("i am test2")
return x*x
test1()
print(test2(3))
执行结果:

i am test1
the func run 3.0068066120147705
i am test2
the func run 3.0043063163757324
9

 总结:test2是有返回值的,所以我们需要在装饰器内部定义一个变量来接收返回值,再return这个变量,最终结果也是有无返回值的函数都正常运行,并且有返回值的函数,返回值也是正确的返回了

 


装饰器四:装饰器本身带参数



posted on 2017-08-16 23:35  clarkxhb  阅读(255)  评论(0编辑  收藏  举报