• 装饰器


    装饰器的使用方法

      1. 先定义一个装饰器
      2. 再定义你的业务函数或者类
      3. 最后把装饰器扣在这个函数头上
    
    # 定义装饰器
    def decorator(func):
          def wrapper(*args, **kw):
                return func()
          return wrapper
    
    # 定义业务函数并进行装饰
    @decorator
    def function():
          print("hello, decorator")
    

    普通装饰器

    • 在函数执行前,先记录一行日志
    • 在函数执行完,再记录一行日志
    def logger(func):
          def wrapper(*args, **kw):
                print('我准备开始执行了:{} 函数了:'.format(func.__name__))
                
                # 真正执行的是这行。
                func(*args, **kw)
    
                print('我执行完啦。')
          return wrapper
    # 业务函数,计算两个数之和
    @logger
    def add(x, y):
          print('{} + {} = {}'.format(x, y, x+y))
    
    add(200, 50)
    
    # 执行结果
    我准备开始执行了: add 函数了:
    200 + 50 = 250
    我执行完啦
    

    带参数的函数装饰器

    def say_hello(country):
          def wrapper(func):
                def deco(*args, **kwargs):
                      if country == "china":
                            print("你好!")
                      elif country == "america"
                            print("hello.")
                      else:
                            return
    
                      # 真正执行函数的地方
                      func(*args, **kwargs)
                return deco
          return wrapper
    
    # 小明,中国人
    @say_hello("china")
    def xiaoming()
          pass
    
    # jack,美国人
    @say_hello("america")
    def jack()
          pass
    
    xiaoming()
    print("------------")
    jack()
    
    # 执行结果
    你好!
    ------------
    hello.
    

    不带参数的类装饰器

    基于类装饰器的实现,必须实现__call____init__两个内置函数
    __init__:接收被装饰函数
    __call__:实现装饰逻辑

    class logger(object):
          def __init__(self, func):
                self.func = func
          
          def __call__(self, *args, **kwargs):
                print("[INFO]:the function {func}() is running...".format(func=self.func__name__))
                return self.func(*args, **kwargs)
    
    @logger
    def say(something):
          print("say {}!".format(something))
    
    say("hello")
    
    # 执行结果
    [INFO]:the function say() is running...
    say hello!
    

    带参数的类装饰器

    不带参数的,只能打印INFO级别的日志,正常情况下,我们还需要打印DEBUG WARNING等级别的日志
    __init__:不再接收被装饰函数,而是接收传入参数
    __call__:接收被装饰函数,实现装饰逻辑

    class logger(object):
          def __init__(self, level='INFO'):
                self.level = level
    
          def __call__(self, func): # 接受函数
                def wrapper(*args, **kwargs):
                      print("[{level}]:the function {func}() is running...".format(level=self.level, func=func.__name__))
                      func(*args, **kwargs)
                return wrapper # 返回函数
    
    @logger(level='WARNING')
    def say(something):
          print("say {}!".format(something))
    
    say("hello")
    
    # 执行结果
    [WARNING]: the function say() is running...
    say hello
    

    使用偏函数与类实现装饰器

    绝大多数装饰器都是基于函数和闭包实现de,但这并非制造装饰器的唯一方式.
    Python对某个对象是否能通过装饰器(@decorator)形式使用只有一个要求:decorator必须是一个"可被调用(callable)的对象".
    对于callable对象,最熟悉的就是函数.除函数外,类也可以是callable对象,只要实现了__call__函数。
    还有偏函数也是callable对象
    DelayFunc是一个实现了__call__的类,delay返回一个偏函数,在这里delay就可以做为一个装饰器.

    import time
    import functools
    
    
    class DelayFunc:
        def __init__(self, duration, func):
            self.duration = duration
            self.func = func
    
        def __call__(self, *args, **kwargs):
            print(f'Wait for {self.duration} seconds...')
            time.sleep(self.duration)
            return self.func(*args, **kwargs)
    
        def eager_call(self, *args, **kwargs):
            print('Call without delay')
            return self.func(*args, **kwargs)
    
    
    def delay(duration):
        """
        装饰器:推迟某个执行函数的执行.
        同时提供 .eager_call 方法立即执行
        """
        # 为了避免定义额外函数,
        # 直接使用 functools.partial 帮助构造DelayFunc 实例
        return functools.partial(DelayFunc, duration)
    
    
    @delay(duration=2)
    def add(a, b):
        return a + b
    
    print(add)
    
    print(add(2, 4))
    
    print(add.func)
    
    # 执行结果
    # add变成了Delay的实例
    # <__main__.DelayFunc object at 0x7f744fd58470>
    # 直接调用实例,进入__call__
    # Wait for 2 seconds...
    # 6
    # 实现实例方法
    # <function add at 0x7f744fd42d08>
    
    Live what we love, do what we do, follow the heart, and do not hesitate.
  • 相关阅读:
    玩具数据库
    数据库中可能会出现的表
    SqlDbHelper
    重写 覆盖 虚方法
    页面标签的初始化
    如何将UTF8转换为UTF8n
    小软件项目开发的管理(转)
    SCRUM软件开发过程(转)
    在.Net如何制作自定义的快捷方式
    What Is a Leader
  • 原文地址:https://www.cnblogs.com/failan/p/14164534.html
Copyright © 2020-2023  润新知