Python函数调用是很慢

这主要是为了确保我的方法是正确的,但我的基本问题是,是否值得它来检查功能之外,如果我需要在所有访问该功能。我知道,我知道过早的优化,但是在许多情况下,它是将if语句放入函数调用以确定我是否需要运行其余代码,还是将其放在函数调用之间的区别。换句话说,无需费力即可以一种或另一种方式进行操作。现在,所有检查都混在两者之间,我希望一切都变得标准化。

我问的主要原因是因为其他答案我看到大多引用timeit,但是这给了我负数,所以我换到这一点:

import timeit

import cProfile

def aaaa(idd):

return idd

def main():

#start = timeit.timeit()

for i in range(9999999):

a = 5

#end = timeit.timeit()

#print("1", end - start)

def main2():

#start = timeit.timeit()

for i in range(9999999):

aaaa(5)

#end = timeit.timeit()

#print("2", end - start)

cProfile.run('main()', sort='cumulative')

cProfile.run('main2()', sort='cumulative')

而得到这个输出

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)

1 0.000 0.000 0.310 0.310 {built-in method exec}

1 0.000 0.000 0.310 0.310 <string>:1(<module>)

1 0.310 0.310 0.310 0.310 test.py:7(main)

1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}

ncalls tottime percall cumtime percall filename:lineno(function)

1 0.000 0.000 2.044 2.044 {built-in method exec}

1 0.000 0.000 2.044 2.044 <string>:1(<module>)

1 1.522 1.522 2.044 2.044 test.py:14(main2)

9999999 0.521 0.000 0.521 0.000 test.py:4(aaaa)

对我来说,这表明,不调用该函数是0.31秒,并调用它需要1.52秒,这是慢了近5倍。但是就像我说的,我得到了负数与timeit,所以我想确保它实际上

缓慢的。

另外从我收集,原因函数调用是如此之慢是因为Python需要仰望确保功能仍然存在,才可以运行它还是什么?是不是有什么办法,只是告诉它喜欢......假设一切都还在那里,以便它没有做无谓的工作,(显然)减慢它的5倍?

回答:

您在这里比较苹果和梨。一种方法进行简单分配,另一种方法调用函数。是的,函数调用 增加开销。

你应该剥离下来到最低限度,为timeit

>>> import timeit

>>> timeit.timeit('a = 5')

0.03456282615661621

>>> timeit.timeit('foo()', 'def foo(): a = 5')

0.14389896392822266

现在我们所做的就是 添加 一个函数调用(foo做同样的事情),所以你可以测量额外时间的函数调用需要。你不能说这是慢了近4倍,没有,函数调用

增加了 0.11的第二顶部为 1.000.000 迭代。

如果不是a = 5我们做一些事情,需要0.5秒,执行一个百万次迭代,将它们转移到一个功能不会让事情需要2秒。现在将花费0.61秒,因为函数开销不会增加。

函数调用需要操纵堆栈,将本地框架推入堆栈,创建新框架,然后在函数返回时再次将其清除。

换句话说,移动报表的功能增加了一个小的开销,而你移动到功能的语句越多,小的开销变得所做的总功的百分比。函数 从来没有 让这些语句本身慢。

Python函数只是存储在变量中的对象。您可以将函数分配给其他变量,用完全不同的变量替换它们,或随时删除它们。调用函数时,首先引用存储它们的名称(foo),然后调用函数对象((arguments))。查找必须每次都使用动态语言进行。

您可以在为函数生成的字节码中看到以下内容:

>>> def foo():

... pass

...

>>> def bar():

... return foo()

...

>>> import dis

>>> dis.dis(bar)

2 0 LOAD_GLOBAL 0 (foo)

3 CALL_FUNCTION 0

6 RETURN_VALUE

LOAD_GLOBAL操作码查找名称(foo)在全局命名空间(基本上是一个哈希表查找),结果压栈。CALL_FUNCTION然后调用堆栈上的所有内容,将其替换为返回值。RETURN_VALUE从函数调用返回,再次以栈顶的任何内容作为返回值。

以上是 Python函数调用是很慢 的全部内容, 来源链接: utcz.com/qa/399840.html

回到顶部