python函数被调用才能执行吗_python – 为什么无争论的函数调用执行得更快?

Why does this happen? Should I avoid specifying argument values during calls?

一般来说,没有.你能够看到的真正原因是因为你使用的功能并不是计算密集型的.因此,可以通过定时检测在提供参数的情况下发出的附加字节代码命令所需的时间.

例如,如果你有一个更加密集的形式的功能:

def foo_intensive(a=10, b=20, c=30, d=40):

[i * j for i in range(a * b) for j in range(c * d)]

它几乎不会显示任何时间的差异:

%timeit foo_intensive()

10 loops, best of 3: 32.7 ms per loop

%timeit foo_intensive(a=10, b=20, c=30, d=40)

10 loops, best of 3: 32.7 ms per loop

即使扩展到更多的呼叫,执行功能体所需的时间也可以简化占用额外字节码指​​令引入的小开销.

查看字节码:

查看为每个调用情况发出的生成的字节码的一种方法是创建一个围绕foo并以不同方式调用它的函数.现在,让我们使用默认参数为fooDefault创建调用,fooKwargs()用于指定关键字参数的函数:

# call foo without arguments, using defaults

def fooDefault():

foo()

# call foo with keyword arguments

def fooKw():

foo(a=10, b=20, c=30, d=40)

现在有了dis,我们可以看到这些之间的字节码的差异.对于默认版本,我们可以看到基本上发出一个命令(忽略在两种情况下都存在的POP_TOP)用于函数调用,CALL_FUNCTION:

dis.dis(fooDefaults)

2 0 LOAD_GLOBAL 0 (foo)

3 CALL_FUNCTION 0 (0 positional, 0 keyword pair)

6 POP_TOP

7 LOAD_CONST 0 (None)

10 RETURN_VALUE

另一方面,在使用关键字的情况下,发出另外8个LOAD_CONST命令,以将参数名称(a,b,c,d)和值(10,20,30,40)加载到值堆栈(即使加载数字<256在这种情况下可能非常快,因为它们被缓存):

dis.dis(fooKwargs)

2 0 LOAD_GLOBAL 0 (foo)

3 LOAD_CONST 1 ('a') # call starts

6 LOAD_CONST 2 (10)

9 LOAD_CONST 3 ('b')

12 LOAD_CONST 4 (20)

15 LOAD_CONST 5 ('c')

18 LOAD_CONST 6 (30)

21 LOAD_CONST 7 ('d')

24 LOAD_CONST 8 (40)

27 CALL_FUNCTION 1024 (0 positional, 4 keyword pair)

30 POP_TOP # call ends

31 LOAD_CONST 0 (None)

34 RETURN_VALUE

另外,关键字参数不为零的情况通常需要一些额外的步骤. (例如ceval/_PyEval_EvalCodeWithName()).

即使这些命令真的很快,他们总结一下.参数越多,总和越大,当许多调用函数实际执行时,这些堆积将导致执行时间的差异.

这些的直接结果是,我们指定的值越多,必须发出的命令越多,函数的运行速度越慢.此外,指定位置参数,解包位置参数和解包关键字参数都具有与它们相关的不同开销:

>位置参数foo(10,20,30,40):需要4个附加命令来加载每个值.

>列出解包foo(* [10,20,30,40]):4个LOAD_CONST命令和一个附加的BUILD_LIST命令.

>使用foo(* l)中的列表可以减少执行,因为我们提供了一个包含值的已经建立的列表.

>字典解包foo(** {‘a’:10,’b’:20,’c’:30,’d’:40}):8 LOAD_CONST命令和BUILD_MAP.

与列表解压缩foo(** d)一样,由于内置的​​列表将被提供,因此将会执行程序.

所有在不同情况下的呼叫执行时间的所有订单是:

defaults < positionals < keyword arguments < list unpacking < dictionary unpacking

我建议在这些情况下使用dis.dis,看看他们的区别.

结论是:

正如@goofd在评论中指出的,这真的是一个不用担心的事情,它确实取决于用例.如果您从计算的角度经常调用“光”功能,则指定默认值会稍微提高速度.如果你经常提供不同的值,那么这个值就不会产生.

所以,这可能是微不足道的,并试图从晦涩的边缘案例中获得提升,因为这真的是推动它.如果你发现自己这样做,你可能想看看像PyPy和Cython这样的事情.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值