博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python三大神器===》装饰器
阅读量:6987 次
发布时间:2019-06-27

本文共 3558 字,大约阅读时间需要 11 分钟。

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就是给参数numberret = test(20)# 注意这里的100其实给参数number_inprint(ret(100))#注 意这里的200其实给参数number_inprint(ret(200))

 运行结果

in test_in 函数, number_in is 100120in test_in 函数, number_in is 200220

看完这段代码我们不妨总结下闭包的作用:  

  1.函数名只是函数代码空间的引用,当函数名赋值给一个对象的时候 就是引用传递

  2.闭包就是一个嵌套定义的函数,在外层运行时才开始内层函数的定义,然后将内部函数的引用传递函数外的对象

  3.内部函数和使用的外部函数提供的变量构成的整体称为闭包

3.初识装饰器

  为什么在解释装饰器时要先了解闭包的概念呢?看完下面的代码你也会就会明白

def decorate(func):    def inner():        return ""+func()+""    return inner@decoratedef func():    return "你好"print(func())

 运行结果

你好

  我们可以看出装饰器就是在闭包的基础上做了一些修改。

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 20183 58foo called at Thu Aug 23 21:30:23 20182 46

5.装饰器不定长传参

from time import ctime, sleepdef timefun(func):    def wrapped_func(*args, **kwargs):        print("%s called at %s"%(func.__name__, ctime()))        func(*args, **kwargs)    return wrapped_func@timefundef 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 20186foo called at Thu Aug 23 21:32:51 201815

 其实这里只是运用了python函数传参时的不定长传参的概念 

6.装饰器中的return

from time import ctime, sleepdef timefun(func):    def wrapped_func():        print("%s called at %s" % (func.__name__, ctime()))        func()    return wrapped_func@timefundef foo():    print("I am foo")@timefundef getInfo():    return '----hahah---'foo()sleep(2)foo()print(getInfo())

 运行结果

foo called at Thu Aug 23 21:36:22 2018I am foofoo called at Thu Aug 23 21:36:24 2018I am foogetInfo called at Thu Aug 23 21:36:24 2018None

7.装饰器工厂(flask定义一个路由的方式)

from time import ctime, sleepdef 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 phpI am foofoo called at Thu Aug 23 21:40:36 2018 phpI am footoo called at Thu Aug 23 21:40:36 2018 pythonI am tootoo called at Thu Aug 23 21:40:38 2018 pythonI 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()@Testdef test():    print("----test---")test()

运行结果

初始化中....func name is test装饰中......----test---

我们也许会发现装饰器中有个很特别的方法__call__(),这个方法时python内置的魔法方法,它作用就是让类能够向函数一样直接被调用,接下来我会专门更新一篇python中的魔法方法,如果想要了解的朋友可以关注我

总结

  1.装饰器函数只有一个参数就是被装饰的函数的应用

  2.装饰器能够将一个函数的功能在不修改代码的情况下进行扩展

  3.在函数定义的上方@装饰器函数名 即可直接使用装饰器对下面的函数进行装饰。

 

 

转载于:https://www.cnblogs.com/xuchuankun/p/9526487.html

你可能感兴趣的文章
python中asynchat异步socket命令/响应处理
查看>>
动态编译
查看>>
linux下批量解压缩
查看>>
一个AD结构引发的Exchange DAG部署问题
查看>>
使用xcopy进行日增量备份
查看>>
我的友情链接
查看>>
知之者不如好之者,好之者不如乐之者
查看>>
测试Application.Idle
查看>>
sizeof与strlen的区别与联系
查看>>
我的友情链接
查看>>
数组名取地址以及数组名作为sizeof操作符的操作数
查看>>
Citrix发布支持Framehawk技术的HDX协议,用户体验优势进一步扩大
查看>>
Android各种访问权限Permission详解
查看>>
asp.net 页面生命周期
查看>>
什么是钩子函数?
查看>>
Linux命令(基本)
查看>>
实战Active Directory站点部署与管理,Active Directory系列之十二
查看>>
信息和知识
查看>>
7.2 函数的参数
查看>>
Flex + Servlet 实现断点上传
查看>>