【问题标题】:Decorator to Find the Time of Execution of a Function in Python在 Python 中查找函数执行时间的装饰器
【发布时间】:2021-08-05 10:08:11
【问题描述】:
from datetime import datetime
import time

def decorating_func(own_func):
    print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
    return own_func

@decorating_func
def addition(num1,num2):
    return num1 + num2

@decorating_func
def multiply(num1,num2):
    return num1 * num2

print(addition(10,5))
time.sleep(71)
print(multiply(10,5))

我是使用装饰器的新手,我希望生成上面的代码

output:
2021-05-15 19:46:01
15
2021-05-15 19:47:11
50

而不是

2021-05-15 19:46:01
2021-05-15 19:46:01
15
50

有人可以解释如何修改上述代码以实现所需的输出吗?

【问题讨论】:

    标签: python python-3.x python-decorators


    【解决方案1】:

    装饰器接受一个函数并返回一个新函数来替换原来的函数。它会立即进行评估。

    所以:

    def decorate(func):
      print("Decorate!")
      return func
    
    @decorate
    def add(x, y):
      return x + y
    

    将打印“装饰!”即使没有调用add

    您要做的是将原始函数“包装”在一个更新的函数中,该函数执行一些工作,然后调用原始函数。

    def decorate(func):
      def _wrap(*args, **kwargs):
        print("Start")
        return func(*args, **kwargs)
    
      return _wrap
    
    @decorate
    def add(x, y):
      return x + y
    

    现在“add”将替换为_wrap,调用它时将首先运行您的打印语句,然后使用相同的参数调用原始函数并返回结果。如果您还想运行一些“发布”逻辑,您可以利用 try...finally:

    def decorate(func):
      def _wrap(*args, **kwargs):
        print("Start")
        try:
           return func(*args, **kwargs)
        finally:
          print("End")
    
      return _wrap
    
    @decorate
    def add(x, y):
      return x + y
    

    finally 块保证执行。如果您不关心在错误情况下打印“End”,您还可以存储返回结果:

    def decorate(func):
      def _wrap(*args, **kwargs):
        print("Start")
        result = func(*args, **kwargs)
        print("End")
        return result
    
      return _wrap
    
    @decorate
    def add(x, y):
      return x + y
    

    如果你需要将参数传递给装饰器,你只需创建一个装饰器工厂,即一个接受一些参数并返回一个装饰函数的函数。

    def makeDecorator(text):
      def decorate(func):
        def _wrap(*args, **kwargs):
          print(f"Start: {text}")
          try:
            return func(*args, **kwargs)
          finally:
            print("End")
        
        return _wrap
      return decorate
    
    @makeDecorator(text="Hi")
    def add(x, y):
      return x + y
    

    关键是装饰器“替换”了被装饰的对象。所以如果你在装饰一个函数,你需要返回一个函数。装饰函数本身并不是调用add() 时调用的函数。

    附加提示:当您返回 _wrap 函数时,其名称将是“_wrap”,而不是原始函数的名称。 functools 标准库提供了一些帮助器,例如 wraps 装饰器,您可以在 _wrap 上使用它来赋予它与原始函数相同的名称。对调试很有用。

    【讨论】:

    • 非常感谢@noahnu。这是非常有用和详细的
    【解决方案2】:

    对于装饰器,你需要一个包装函数,看看我的代码。我推荐这个视频来学习装饰器:https://www.youtube.com/watch?v=r7Dtus7N4pI.

    代码:

    from datetime import datetime
    import time
    
    def decorating_func(own_func):
        def wrapper(*args, **kwargs):
            print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
            return own_func(*args, **kwargs)
        return wrapper
    
    @decorating_func
    def addition(num1,num2):
        return num1 + num2
    
    @decorating_func
    def multiply(num1,num2):
        return num1 * num2
    
    print(addition(10,5))
    time.sleep(71)
    print(multiply(10,5))
    

    【讨论】:

      猜你喜欢
      • 2016-07-25
      • 1970-01-01
      • 2015-06-16
      • 1970-01-01
      • 2015-05-27
      • 2019-04-13
      • 1970-01-01
      • 2020-07-13
      相关资源
      最近更新 更多