【问题标题】:Python: How can i convert this into a decoratorPython:如何将其转换为装饰器
【发布时间】:2017-07-20 19:58:10
【问题描述】:

我一辈子都想不通如何把它变成一个装饰器。 任何帮助或示例都会很棒。

这里是代码

import datetime    

def time_func(function, *args, **kwargs):
  '''
  Add the execution time to a functions attributes 
  '''
  # Start the clock.
  start = datetime.datetime.now()
  # Execute the function and record the results.
  function_result = function(*args, **kwargs)
  # Calculate the elapsed time and add it to the function
  # attributes.
  function.elapsed = datetime.datetime.now() - start
  # Returned the function with the added elapsed attribute 
  return function_result

这是一个使用示例

.. import datetime 
..  
..  
.. def time_func(function, *args, **kwargs): 
..   ''' 
..   Add the execution time to a functions attributes  
..   ''' 
..   # Start the clock. 
..   start = datetime.datetime.now() 
..   # Execute the function and record the results. 
..   function_result = function(*args, **kwargs) 
..   # Calculate the elapsed time and add it to the function 
..   # attributes. 
..   function.elapsed = datetime.datetime.now() - start 
..   # Returned the function with the added elapsed attribute  
..   return function_result 
..    
..  
.. def f(name): 
..   print name 
..    
.. time_func(f, 'foo') 
.. print f.elapsed 
.. 
foo
0:00:00.000115

【问题讨论】:

  • 查看post
  • 您是否考虑过使用timeit 模块?

标签: python performance time


【解决方案1】:

装饰器只是一个接受一个函数并返回一个函数的函数。

import datetime

def time_func(function):
    # create a new function based on the existing one,
    # that includes the new timing behaviour
    def new_func(*args, **kwargs):
        # Start the clock.
        start = datetime.datetime.now()
        # Execute the function and record the results.
        function_result = function(*args, **kwargs)
        # Calculate the elapsed time and add it to the function
        # attributes.
        new_func.elapsed = datetime.datetime.now() - start
        # Returned the function with the added elapsed attribute 
        return function_result
    return new_func

用法:

@time_func
def f(name):
    print(name)

f('foo')
print(f.elapsed)
> foo
> 0:00:00.000045

查看functools.wraps 以进一步改进装饰器。

【讨论】:

    【解决方案2】:

    定义一个内部函数:

    import datetime    
    
    def time_func(function):
        '''
        Add the execution time to a functions attributes 
        '''
        def func(*args, **kwargs):
            start = datetime.datetime.now()
            function_result = function(*args, **kwargs)
            func.elapsed = datetime.datetime.now() - start
            return function_result
        return func
    
    @time_func
    def f(name):
        print name
    

    【讨论】:

      【解决方案3】:

      制作装饰器的常用方法是使用两个嵌套函数:

      def time_func(function):
        def wrapper(*args, **kwargs):
            start = datetime.datetime.now()
            function_result = function(*args, **kwargs)
            wrapper.elapsed = datetime.datetime.now() - start
            return function_result
         return wrapper
      

      此代码与您的原始代码之间的唯一主要区别(除了去掉 cmets 的空间)是 function 是通过调用外部函数提供的,而其他参数则提供给包装函数。我们还需要将elapsed 时间保存在wrapper 函数上,而不是原来的函数上(因为当你是装饰者时,原来的函数将无法访问)。

      【讨论】:

      • 这不起作用,因为function.elapsed 将结果保存到旧函数而不是包装函数。相反,请使用wrapper.elapsed
      猜你喜欢
      • 2018-07-18
      • 1970-01-01
      • 2011-03-18
      • 2020-02-10
      • 1970-01-01
      • 2015-01-05
      • 1970-01-01
      • 2010-11-24
      • 2021-04-21
      相关资源
      最近更新 更多