装饰器为Python函数调用添加了多少开销

时间:2010-08-23 08:06:09

标签: python performance decorator

我一直在玩我的挂架应用程序的计时装饰器,以便为特定功能提供即时通讯信息。我是通过创建一个装饰器来做到这一点的。只需将它附加到我想要定时的控制器中的任何功能。

但是有人指出装饰器可能会给调用增加相当大的开销,并且它们比未修饰的函数运行速度慢2-3倍。

首先,我希望执行一个装饰的函数比一个未修饰的函数更长一些,但我希望这个开销可以在千分之一秒内完成。与SQL插入调用相比可忽略不计。装饰器本身使用time.time()& amp;进行简单的简单计时计算。一些非常简单的聚合。

装饰器是否会给系统增加很多开销?我找不到任何支持它的东西。

3 个答案:

答案 0 :(得分:13)

使用装饰器添加的开销应该只是一个额外的函数调用。

装饰器完成的工作不是开销的一部分,因为您可以选择将等效代码添加到装饰对象中。

因此,装饰函数可能需要两倍的时间才能运行,但这是因为装饰器正在做一些重要的工作,它们与未修饰的函数的工作时间大致相同。

答案 1 :(得分:5)

重要的是要知道装饰器有一个简单的效果:

@decorator
def f():
    …

只是

的语法糖
def f():
    …
f = decorator(f)

因此,如果装饰器没有做任何事情,那么当调用装饰函数时,你没有任何开销(虽然调用decorator(f)确实需要一点时间),就像在< / p>

decorator = lambda func: func
@decorator
def f():
    …

如果装饰者做了什么,你只能获得装饰者所涉及的任何时间。这通常包括一个额外的函数调用(装饰函数的调用),如

def decorator(func):
    def decorated_func():
        print "Before calling function", func  # Some overhead (but that's normal)
        func()  # This will be a second function call, after the call to decorated_func()
    return decorated_func

因此,装饰函数本身并没有为你想要做的事情增加太多开销:你原则上可以删除的唯一明显的开销是不在装饰函数中调用func()而是复制它的完整代码,但代码的易读性将受到影响(易读性和灵活性是装饰者首先存在的一些原因)。

答案 2 :(得分:3)

  

装饰器是否会给系统增加很多开销?我找不到任何支持它的东西。

他们几乎没有增加可衡量的开销。零。

重要的是要注意装饰器运行一次以创建装饰函数。 一次。

装饰功能有两个部分。

  1. 无论添加什么装饰。这不是开销。

  2. 加上原始功能。这不是开销。

  3. 根本没有真正的开销。你可以 - 小心谨慎 - 能够测量一个额外函数调用和返回的开销,作为一个装饰函数的一部分,但这几乎是不可测量的小。它可能远远不如不使用装饰的替代设计。