zoukankan      html  css  js  c++  java
  • python三大神器===》装饰器

    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())
    

     运行结果

    <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.在函数定义的上方@装饰器函数名 即可直接使用装饰器对下面的函数进行装饰。

     

  • 相关阅读:
    注册界面测试案例注意点
    linux常用命令
    linux常用快捷键总结
    2015.8.29某高级企业的在线笔试题
    图像处理------直方图均衡化
    “猫叫系统”开启了观察者模式
    Hua Wei 机试题目四---2014
    Hua Wei 机试题目三---2014
    Hua Wei 机试题目二
    Hua Wei 机试题目一
  • 原文地址:https://www.cnblogs.com/xuchuankun/p/9526487.html
Copyright © 2011-2022 走看看