zoukankan      html  css  js  c++  java
  • python装饰器介绍

    """
    装饰器
    定义:本质是函数(器:就是函数的意思),功能:装饰其他函数,就是为其他函数添加附加功能

    原则:
    1. 不能修改被装饰的函数的源代码
    2. 不能修改被装饰的函数的调用方式

    实现装饰器知识储备:
    1. 函数即"变量"
    2. 高阶函数
    a: 把一个函数名当做实参传给另一个函数(在不修改被装饰函数源代码的情况下为其添加功能)
    b: 返回值中包含函数名 (不修改函数的调用方式)
    3. 嵌套函数

    高阶函数 + 嵌套函数 --> 装饰器

    参考链接:http://egon09.blog.51cto.com/9161406/1836763
    """


    # 将test1 和 test2 函数添加logging 功能 (未使用使用函数调用)
    '''
    def logger():
        print ("logging")
    
    def test1():
        pass
        logger()
    
    def test2():
        pass
        logger()
    
    test1()
    test2()
    '''




    # 装饰器示范_1
    '''
    import time
    
    def timmer(func):
        def warpper(*args,**kwargs):
            start_time = time.time()
            func()
            stop_time = time.time()
            print ("the func run time is %s"%(stop_time - start_time))
        return warpper
    
    @timmer
    def test1():
        time.sleep(3)
        print ("this is test1")
    
    test1()
    # this is test1
    # the func run time is 3.019197702407837
    
    '''



    # 函数即"变量"
    # 新概念:函数在内存中以变量形式存放
    # 匿名函数没有函数名,当运行后内存会被立马回收(def 定义的函数,不会被内存回收,当程序结束后内存地址才会释放)
    '''
    # eg_v1  
    def bar():  # 正常运行
        print ("in the bar")
    def foo():
        print ("in the foo")
        bar()
    foo()
    # in the foo
    # in the bar
    
    
    # eg_v2   # 正常运行
    def foo():
        print ("in the foo")
        bar()
    def bar():
        print ("in the bar")
    foo()
    # in the foo
    # in the bar
    
    
    # eg_v3  # 抛出异常
    def foo():
        print ("in the foo")
        bar()
    foo()
    def bar():
        print ("in the bar")
    # Traceback (most recent call last):
    # in the foo
    #   File "E:/pycharm-project/PYTHON自动化课程/第二模块/课堂笔记/装饰器_v1.py", line 92, in <module>
    #     foo()
    #   File "E:/pycharm-project/PYTHON自动化课程/第二模块/课堂笔记/装饰器_v1.py", line 91, in foo
    #     bar()
    # NameError: name 'bar' is not defined
    '''


    # 高阶函数
    # eg_v1
    '''
    def bar():
        print ("in the bar")
    
    def test1(func):
        print (func)
    # test1(bar)
    # # <function bar at 0x0000024DE92E3E18> bar函数的内存地址
    '''
    
    # eg_v2
    '''
    def bar():
        print ("in the bar")
    
    def test1(func):
        print (func)
        func()     # 2 调用func函数时,也运行了bar函数
    test1(bar)     # 1 将bar函数传递给test1
    # <function bar at 0x00000216F49D3E18>
    # in the bar
    '''
    
    
    # eg_v3  # 装饰器第一步(没有修改源代码,但改变了调用方式)(test1为装饰函数,bar函数为被装饰函数)
    '''
    import time
    def bar():
        time.sleep(2)
        print ("in the bar")
    
    def test1(func):
        start_time = time.time()
        func()
        stop_time = time.time()
        print ("the func run time is %s"%(stop_time - start_time))
    
    test1(bar)
    # in the bar
    # the func run time is 2.000016689300537
    '''
    
    # eg_v4
    
    '''
    import time
    def bar():
        time.sleep(2)
        print("in the bar")
    
    def test2(func):
        print (func)
        return func
    # t = test2(bar)  # 将test2(bar) 赋值给t,t() == 调用test2函数,改变了调用方式
    # t()
    # # <function bar at 0x00000172B2CF3E18>
    # # in the bar
    bar = test2(bar)    # # 将test2(bar) 赋值给bar,bar() == 调用test2函数,未改变了调用方式
    bar()
    # <function bar at 0x0000016C6E663E18>
    # in the bar
    '''
    

      



    # 嵌套函数
    # eg_v1
    '''
    def foo():
        print ("in the foo")
        def bar():
            print ("in the bar")
    
        bar()
    foo()
    '''
    
    # eg_v2 # 局部作用域和全局作用域的访问顺序
    '''
    x = 0
    def grandpa():
        x = 1
        def dad():
            x = 2
            def son():
                x = 3
                print (x)
            son()
        dad()
    grandpa()
    # 3
    '''
    

      





    # 写一个简单的装饰器
    # eg_v1 不使用语法糖
    '''
    import time
    
    def timer(func):   # timer(test1) --> func= test1
        def deco():
            start_time = time.time()
            func()   # run test1()
            stop_time = time.time()
            print ("the func run time %s:"%(stop_time - start_time))
        return deco
    
    def test1():
        time.sleep(3)
        print ("in the test1")
    
    def test2():
        time.sleep(3)
        print ("in the test2")
    test1 = (timer(test1))  # 赋值必须与被装饰的函数同名
    test1()
    # in the test1
    # the func run time 3.0068588256835938:
    '''


    # eg_v2 使用语法糖,不带参数
    '''
    import time
    
    def timer(func):   # timer(test1) --> func= test1
        def deco():
            start_time = time.time()
            func()   # run test1()
            stop_time = time.time()
            print ("the func run time %s:"%(stop_time - start_time))
        return deco
    
    @timer
    def test1():
        time.sleep(3)
        print ("in the test1")
    @timer
    def test2():
        time.sleep(3)
        print ("in the test2")
    
    test1()
    test2()
    # in the test1
    # the func run time 3.000098705291748:
    # in the test2
    # the func run time 3.0001633167266846:
    '''



    # eg_v2 使用语法糖,被装饰函数带参数
    '''
    import time
    
    def timer(func):   # timer(test1) --> func= test1
        def deco(*args,**kwargs):
            start_time = time.time()
            func(*args,**kwargs)   # run test1()
            stop_time = time.time()
            print ("the func run time %s:"%(stop_time - start_time))
        return deco
    
    @timer
    def test1():
        time.sleep(3)
        print ("in the test1")
    @timer
    def test2(name):   # test2 = timer(test2) == deco test2(name) == deco(name)
        time.sleep(3)
        print ("in the test2",name)
    
    test1()
    test2("xieshengsen")
    # in the test1
    # the func run time 3.0004942417144775:
    # in the test2 xieshengsen
    # the func run time 3.0003535747528076:
    '''



    # eg_v3
    # 一个简单的登陆页面认证过程(装饰器)(装饰函数带参数)
    user = "aaaaaa"
    pawd = "123456"
    
    
    def auth(auth_type):
        print ("auth func:",auth_type)
        
        def outer_wrapper(func):
            def wrapper(*args,**kwargs):
                print ("wrapper func args:",*args,**kwargs)
    
                if auth_type == "local":
                    username = input("username:").strip()
                    password = input("password:").strip()
    
                    if username == user and password == pawd:
                        print ("login....")
                        res = func(*args,**kwargs)  # from home
                        print ("-*-*-*-*-after auth-*-*-*-*-")
                        return res
                    else:
                        print ("invalid...")
                elif auth_type == "ldap":
                    input("ldap")
                    print ("use ladp auth...")
            return wrapper
        return outer_wrapper
    
    
    def index():
        print ("welcome to index page.")
        
    
    @auth(auth_type="local")
    def home():
        print("welcome to home age.")
    
    
    @auth(auth_type="ldap")
    def bbs():
        print("welcome to bbs age.")
    
    index()
    home()
    bbs()
    

      

    另 一些关于装饰器介绍的实例

    来自:http://blog.csdn.net/yhy1271927580/article/details/72758577

    """
    被装饰的对象为函数,且不带参数
    简要说明: @timeit装饰器对sleep函数进行了装饰,这是一个装饰器不带参数的装饰器,当sleep函数调用的时候,调用的并不是我们看到的原始的sleep函数,而是装饰过后的sleep函数。这个装饰的过程会发生在调用sleep函数之前发生。
    装饰的过程:原生的sleep函数作为参数传递到timeit装饰器函数的fn参数,通过@wraps这个装饰器将fn的属性赋值给底下需要返回的wrap函数,最后返回wrap函数,由此可间,wrap就是装饰过后的sleep函数了。那么在调用新sleep函数的时候,就是调用wrap函数,sleep函数的参数2,被wrap函数的*args、**kwargs这两个可变参数接收。
    整个装饰的目的就是将原生的sleep函数,扩充了一个print(nowTime() - start)的过程。
    """
    from time import sleep as sleeping
    from time import time as nowtime
    from functools import wraps
    
    
    def timeit(fn):
        @wraps(fn)
        def wrap(*args,**kwargs):
            start = nowtime()
            ret = fn(*args,**kwargs)
            print (nowtime() - start)
            return ret
        return wrap
    
    @timeit
    def sleep(n):
        sleeping(n)
        print("sleep time {}s".format(n))
        return n
    
    sleep(2)
    print("%s func" % sleep.__name__)
    # sleep time 2s
    # 2.0028135776519775
    # sleep func
    

      

    """
    被装饰的对象为函数,且带参数
    简要说明: @timeit装饰器对sleep函数进行了装饰,这是一个装饰器是带参数的装饰器.
    这个装饰器由于需要传递参数,因此需要两层装饰,第一层是接受传递的参宿,第二层是接收传递进来的需要装饰的函数当sleep函数调用的时候,调用的并不是我们看到的原始的sleep函数,而是装饰过后的sleep函数。
    装饰的过程:装饰器第一次接收cpu_time参数,然后返回一个dec装饰器,而这个dec装饰器会被再次调用,传入参数是原生的sleep函数,原生的sleep函数作为参数传递到dec装饰器函数的fn参数,通过@wraps这个装饰器将fn的属性赋值给底下需要返回的wrap函数,最后返回wrap函数
    在调用新sleep函数的时候,就是调用wrap函数,sleep函数的参数2,被wrap函数的*args、**kwargs这两个可变参数接收。整个装饰的目的就是将原生的sleep函数,扩充了一个time_func = time.clock if cpu_time else time.time和print(nowTime() - start)的过程
    """
    from functools import wraps
    import time
    
    
    def timeit(cpu_time=False):
        print("timeit")
    
        def dec(fn):
            @wraps(fn)
            def wrap(*args,**kwargs):
                start = time.time()
                ret = fn (*args,**kwargs)
                print(time.time() - start)
                return ret
            return wrap
        return dec
    
    
    @timeit(False)
    def sleep(n):
        time.sleep(n)
        print ("time sleep")
        return n
    
    sleep(2)
    print("%s func" % sleep.__name__)
    # timeit
    # time sleep
    # 2.009625196456909
    # sleep func
    

      





  • 相关阅读:
    linux 查看僵尸进程
    apache 修改最大连接数
    ng压缩后,形参被简化问题解决:
    $rootScope 与 $scope 区别:$rootScope对象是“单例的”——一个模块中只有一个$rootScope;
    vue+webpack在“双十一”导购产品的技术实践
    过滤指令:number currency lowercase(转为小写)/uppercase(转为大写)
    ng-show ng-disabled ng-show ng-hide 值的布尔值改变时,状态发生变化
    二,数据双向绑定
    一、angular:module-Controller-Model-View (模块-控制器-模型-视图);异步请求$http
    5、面向对象
  • 原文地址:https://www.cnblogs.com/xieshengsen/p/7301889.html
Copyright © 2011-2022 走看看