1.认识装饰器
如果你经常看我的博客,你已经学会了python的前两大‘神器’(迭代器,生成器),那么什么是装饰器呢?就如字面意义装饰器是对某个事物(通常指函数)进行装饰,让其在不修改任何内部代码的情况下增添新的功能,接下来我将一步步的解析python的装饰器。
2.闭包
在解析装饰器之前我们需要先了解下闭包的概念,我们先通过一段代码了解闭包
# 定义一个函数 def test(number): # 在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包 def test_in(number_in): print ( "in test_in 函数, number_in is %d" % number_in) return number + number_in # 其实这里返回的就是闭包的结果 return test_in # 给test函数赋值,这个20就是给参数number ret = test( 20 ) # 注意这里的100其实给参数number_in print (ret( 100 )) #注 意这里的200其实给参数number_in print (ret( 200 )) |
运行结果
in test_in 函数, number_in is 100 120 in test_in 函数, number_in is 200 220 |
看完这段代码我们不妨总结下闭包的作用:
1.函数名只是函数代码空间的引用,当函数名赋值给一个对象的时候 就是引用传递
2.闭包就是一个嵌套定义的函数,在外层运行时才开始内层函数的定义,然后将内部函数的引用传递函数外的对象
3.内部函数和使用的外部函数提供的变量构成的整体称为闭包
3.初识装饰器
为什么在解释装饰器时要先了解闭包的概念呢?看完下面的代码你也会就会明白
def decorate(func): def inner(): return "<i>" + func() + "</i>" return inner @decorate def func(): return "你好" print (func()) |
运行结果
1 | <i>你好< / i> |
我们可以看出装饰器就是在闭包的基础上做了一些修改。
4.装饰器普通传参
from time import ctime, sleep def timefun(func): def wrapped_func(a, b): print("%s called at %s" % (func.__name__, ctime())) print(a, b) func(a, b) return wrapped_func @timefun def foo(a, b): print(a+b) foo(3,5) sleep(2) foo(2,4)
运行结果
foo called at Thu Aug 23 21 : 30 : 21 2018 3 5 8 foo called at Thu Aug 23 21 : 30 : 23 2018 2 4 6 |
5.装饰器不定长传参
from time import ctime, sleep def timefun(func): def wrapped_func( * args, * * kwargs): print ( "%s called at %s" % (func.__name__, ctime())) func( * args, * * kwargs) return wrapped_func @timefun def foo(a, b, c): print (a + b + c) foo( 1 , 2 , 3 ) sleep( 1 ) foo( 4 , 5 , 6 ) |
运行结果
foo called at Thu Aug 23 21 : 32 : 50 2018 6 foo called at Thu Aug 23 21 : 32 : 51 2018 15 |
其实这里只是运用了python函数传参时的不定长传参的概念
6.装饰器中的return
from time import ctime, sleep def timefun(func): def wrapped_func(): print ( "%s called at %s" % (func.__name__, ctime())) func() return wrapped_func @timefun def foo(): print ( "I am foo" ) @timefun def getInfo(): return '----hahah---' foo() sleep( 2 ) foo() print (getInfo()) |
运行结果
foo called at Thu Aug 23 21 : 36 : 22 2018 I am foo foo called at Thu Aug 23 21 : 36 : 24 2018 I am foo getInfo called at Thu Aug 23 21 : 36 : 24 2018 None |
7.装饰器工厂(flask定义一个路由的方式)
from time import ctime, sleep def timefun_arg(pre = "hello" ): def timefun(func): def wrapped_func(): print ( "%s called at %s %s" % (func.__name__, ctime(), pre)) return func() return wrapped_func return timefun @timefun_arg ( "php" ) def foo(): print ( "I am foo" ) @timefun_arg ( "python" ) def too(): print ( "I am too" ) foo() sleep( 2 ) foo() too() sleep( 2 ) too() |
运行结果
foo called at Thu Aug 23 21 : 40 : 34 2018 php I am foo foo called at Thu Aug 23 21 : 40 : 36 2018 php I am foo too called at Thu Aug 23 21 : 40 : 36 2018 python I am too too called at Thu Aug 23 21 : 40 : 38 2018 python I am too |
我们分析下装饰器工厂装饰过程
1. 调用timefun_arg("itcast")
2. 将步骤1得到的返回值,即time_fun返回, 然后time_fun(foo)
3. 将time_fun(foo)的结果返回,即wrapped_func
4. 让foo = wrapped_fun,即foo现在指向wrapped_func
8.类装饰器
class Test( object ): def __init__( self , func): print ( "初始化中...." ) print ( "func name is %s" % func.__name__) self .__func = func def __call__( self ): print ( "装饰中......" ) self .__func() @Test def test(): print ( "----test---" ) test() |
运行结果
初始化中.... func name is test 装饰中...... - - - - test - - - |
我们也许会发现装饰器中有个很特别的方法__call__(),这个方法时python内置的魔法方法,它作用就是让类能够向函数一样直接被调用,接下来我会专门更新一篇python中的魔法方法,如果想要了解的朋友可以关注我
总结
1.装饰器函数只有一个参数就是被装饰的函数的应用
2.装饰器能够将一个函数的功能在不修改代码的情况下进行扩展
3.在函数定义的上方@装饰器函数名 即可直接使用装饰器对下面的函数进行装饰。
原文出处:https://www.cnblogs.com/xuchuankun/p/9526487.html
共同学习,写下你的评论
评论加载中...
作者其他优质文章