zoukankan      html  css  js  c++  java
  • 装饰器

    装饰器

    • 最简装饰器

        def deco(func):
            def wrap(*args, **kwargs):
                return func(*args, **kwargs)
            return wrap
        @deco
        def foo(a, b):
            return a ** b
       
    • 原理

      • 对比被装饰前后的 foo.__name__foo.__doc__

          from functools import wraps
          def deco(func):
              '''i am deco'''
              @wraps(func)  # 还原被装饰器修改的原函数属性
              def wrap(*args, **kwargs):
                  '''i am wrap'''
                  return func(*args, **kwargs)
              return wrap
         
      • 简单过程

          fn = deco(func)
          foo = fn
          foo(*args, **kwargs)
         
      • 多个装饰器叠加调用的过程

          @deco1
          @deco2
          @deco3
          def foo(x, y):
              return x ** y
          # 过程拆解 1
          fn3 = deco3(foo)
          fn2 = deco2(fn3)
          fn1 = deco1(fn2)
          foo = fn1
          foo(3, 4)
          # 过程拆解 2
          # 单行: deco1( deco2( deco3(foo) ) )(3, 2)
          deco1(
              deco2(
                  deco3(foo)
              )
          )(3, 4)
         
    • 带参数的装饰器

        def deco(n):
            def wrap1(func):
                def wrap2(*args, **kwargs):
                    return func(*args, **kwargs)
                return wrap2
            return wrap1
        # 调用过程
        wrap1 = deco(n)
        wrap2 = wrap1(foo)
        foo = wrap2
        foo()
        # 单行形式
        check_result(30)(foo)(4, 8)
       
    • 装饰器类和 __call__

        class Deco:
            def __init__(self, func):
                self.func = func
            def __call__(self, *args, **kwargs):
                return self.func(*args, **kwargs)
        @Deco
        def foo(x, y):
            return x ** y
        # 过程拆解
        fn = Deco(foo)
        foo = fn
        foo(12, 34)
       
    • 使用场景

      • 参数、结果检查

      • 缓存、计数

      • 日志、统计

      • 权限管理

      • 重试

      • 其他

    • 练习1: 写一个 timer 装饰器, 计算出被装饰函数调用一次花多长时间, 并把时间打印出来

        import time
        from functools import wraps
        def timer(func):
            @wraps(func)  # 修正 docstring
            def wrap(*args, **kwargs):
                time0 = time.time()
                result = func(*args, **kwargs)
                time1 = time.time()
                print(time1 - time0)
                return result
            return wrap
       
    • 练习2: 写一个 Retry 装饰器

        import time
        class retry(object):
            def __init__(self, max_retries=3, wait=0, exceptions=(Exception,)):
                self.max_retries = max_retries
                self.exceptions = exceptions
                self.wait = wait
            def __call__(self, func):
                def wrapper(*args, **kwargs):
                    for i in range(self.max_retries + 1):
                        try:
                            result = func(*args, **kwargs)
                        except self.exceptions:
                            time.sleep(self.wait)
                            continue
                        else:
                            return result
                return wrapper
       
  • 相关阅读:
    tcp_wrapper过滤
    cobbler无人值守批量安装Linux系统
    PXE+kickstart无人值守安装CentOS 7
    kickstart文件详解
    SHELL脚本--shell数组基础
    SHELL脚本--管道和重定向基础
    第4章 DHCP服务
    第3章 NFS基本应用
    man sm-notify(sm-notify命令中文手册)
    man statd(rpc.statd中文手册)
  • 原文地址:https://www.cnblogs.com/gugubeng/p/9755271.html
Copyright © 2011-2022 走看看