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

doc*_*ead 17 python performance decorator

我一直在玩我的挂架应用程序的计时装饰器,以便为特定功能提供即时通讯信息.我通过创建一个装饰器并简单地将它附加到我想要的控制器中的任何函数来完成此操作.

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

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

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

Joh*_*ooy 12

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

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

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


Eri*_*got 5

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

@decorator
def f():
    …
Run Code Online (Sandbox Code Playgroud)

只是语法糖

def f():
    …
f = decorator(f)
Run Code Online (Sandbox Code Playgroud)

因此,如果装饰器没有做任何事情,那么在调用装饰函数时你没有任何开销(虽然调用decorator(f)需要一点时间),比如

decorator = lambda func: func
@decorator
def f():
    …
Run Code Online (Sandbox Code Playgroud)

如果装饰器做任何事情,你只能得到装饰者所涉及的任何时间.这通常包括一个额外的函数调用(装饰函数的函数调用),如

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
Run Code Online (Sandbox Code Playgroud)

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

  • -1 Python 中的函数调用开销并非微不足道。并且建议将 `func()` 的代码复制到装饰器中,一开始就违背了装饰器的全部意义。如果有的话,我更愿意将装饰器的代码复制到 `func()` 中,但同样,如果我们这样做,使用装饰器的简单性就会被破坏,并且 `func()` 的代码会被装饰行为污染。你真的不能说“如果装饰器不做任何事情,你就没有任何开销”。装饰器对于代码跟踪等很有用,但它们的代价是在运行时添加函数调用。 (3认同)