zoukankan      html  css  js  c++  java
  • python装饰器执行顺序

    . python 装饰器

        1) 2层装饰器       

    复制代码
    def decorator(func):
        # TODO
        def wrapper(*args, **kwargs):
            # TODO
            func(*args, **kwargs)
            # TODO
        # TODO
        return wrapper
    复制代码

       2)  3层装饰器

    复制代码
    def decorator3(a=0, b=0):
    
        # TODO
        def wrapper(func):
            # TODO
            def inner_wrapper(*args, **kwargs):
                # TODO
                func(*args, **kwargs)
                # TODO
            # TODO
            return inner_wrapper
        # TODO
        return wrapper
    复制代码

    此处a,b可为任意指定参数,但不可以更改。

     3) 类装饰器, python中类本身是不可调用的, 需要实现__call__方法, 将类变为callable。   

    复制代码
    class decorator(object):
    
        def __init__(self, func):
            self.func = func
    
        def __call__(self, *args, **kwargs):
            # TODO
            self.func(*args, **kwargs)
            # TODO
    复制代码
    复制代码
    class decorator2(object):
    
        def __call__(self, func):
            # TODO
            def wrapper(*args, **kwargs):
                # todo
                func(*args, **kwargs)
                # todo
            # TODO
            return wrapper
    复制代码

    python装饰器使用闭包的方式提供aop的概念。不过需要注意,装饰器装饰的函数,无法通过func.__name__获得真正的函数名, 可以导入functools.wraps包装。

    wraps实际上调用的update_wrapper。

    2. python装饰器的执行顺序。

    复制代码
     1 import time
     2 
     3 
     4 def log(level="info"):
     5     print "log"
     6 
     7     def wrapper(f):
     8         print "wrapper start"
     9 
    10         def inner_wrapper(*args, **kwargs):
    11             print "inner_wrapper start"
    12             print "{0}: {1}".format(level, time.time())
    13             f(*args, **kwargs)
    14             print "{0}: {1}".format(level, time.time())
    15             print "inner_wrapper end"
    16 
    17         print "wrapper end"
    18         return inner_wrapper
    19 
    20     print "end"
    21     return wrapper
    22 
    23 
    24 def log2(f):
    25     print "log2..."
    26 
    27     def wrapper(*args, **kwargs):
    28         print "log2"
    29         f(*args, **kwargs)
    30         print "log2"
    31 
    32     print "log2..."
    33     return wrapper
    34 
    35 
    36 @log2
    37 @log(level="debug")
    38 def test(a, b):
    39     print a, b
    复制代码

    执行test,输出

    参见:https://segmentfault.com/a/1190000007837364

    多个装饰器是按从下到上的顺序执行的, 在上图的例子中,test可以简化为test=log2(log(test)), 先执行log装饰器inner_wrapper外层的,得到inner_wrapper, 此时inner_wrapper是log2, 得到log2的wrapper, 此wrapper封装的func是log的inner_wrapper, 依次顺序执行,

    结果如上图所示。

  • 相关阅读:
    k8spod资源的基础管理操作
    k8s名称空间资源
    bzoj5011: [Jx2017]颜色
    bzoj5010: [Fjoi2017]矩阵填数
    bzoj5008: 方师傅的房子
    bzoj5007: TCP协议
    bzoj5003: 与链 5004: 开锁魔法II 5005:乒乓游戏
    bzoj5020: [THUWC 2017]在美妙的数学王国中畅游
    bzoj5006: [THUWC2017 Bipartite]随机二分图
    bzoj4480: [Jsoi2013]快乐的jyy
  • 原文地址:https://www.cnblogs.com/ExMan/p/10171067.html
Copyright © 2011-2022 走看看