在 Python 中查找函数执行时间的装饰器

Decorator to Find the Time of Execution of a Function in Python

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

有人可以解释应该如何修改以上代码以获得所需的输出吗?

作为装饰器,里面需要一个包装函数,看我的代码。我推荐这个视频来学习装饰器: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))

一个装饰器接受一个函数,return一个新函数来替换原来的函数。立即评估。

所以:

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 替换,调用时将首先 运行 您的打印语句,然后使用相同的参数和 return 结果调用原始函数。如果你也想运行一些“post”逻辑,你可以尝试一下......最后:

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”,您还可以存储 return 结果:

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

如果您需要将 args 传递给装饰器,您只需创建一个装饰器工厂,即一个接受一些 args 和 returns 装饰函数的函数。

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

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

时调用的函数

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