Skip to main content
 首页 » 编程设计

python之元组理解时间分析

2025年05月04日11zdz8207

最近我一直在分析我的脚本。 想知道元组理解我在 SO 上发现了几个线程,指出了两种方法:

  • 列表推导 + 元组()

    >>> tuple([i for i in xrange(1000000)]) 
    
  • 元组理解

    >>> tuple(i for i in xrange(1000000)) 
    

cProlile 和 timeit 告诉我第一种方法比第二种方法更快,而且命令行 time 和 kernprof 线路分析器说的恰恰相反。

这是我得到的:

>>> import cProfile 
>>> cProfile.run('tuple([i for i in xrange(1000000)])') 
1000003 function calls in 0.139 seconds 
>>> cProfile.run('tuple(i for i in xrange(1000000))') 
1000003 function calls in 0.478 seconds  
 
>>> import timeit 
>>> timeit.timeit('tuple([i for i in xrange(1000000)])') 
0.08100390434265137 
>>> timeit.timeit('tuple(i for i in xrange(1000000))') 
0.08400511741638184 

使用 test_tuple_list.py:

tuple([i for i in xrange(1000000)]) 

和 test_tuple_generator.py:

tuple(i for i in xrange(1000000)) 

我得到:

$time python test_tuple_list.py 
real 0m0.398s 
user 0m0.171s 
sys 0m0.202s 
 
$time python test_tuple_generator.py 
real 0m0.333s 
user 0m0.109s 
sys 0m0.234s 

使用 test_tuple_list_kernprof.py

@profile 
def test(): 
    tuple([i for i in xrange(1000000)]) 
test() 

和 test_tuple_generator_kernprof.py:

@profile 
def test(): 
   tuple(i for i in xrange(1000000)) 
test() 

我得到:

$kernprof.py -lv test_tuple_list_kernprof.py 
Total time: 0.861045 s 
 
$kernprof.py -lv test_tuple_generator_kernprof.py 
Total time: 0.444025 s 

我认为这些分析器之间的差异在于它们分析的方式,但它们怎么会相互矛盾呢?

谢谢

请您参考如下方法:

不要使用探查器来测量两个 Python 代码片段之间的整体时间差异。配置文件严重会影响整个解释器的代码执行时间,因为不同的代码路径会触发 sys.set_trace() trace function在不同的时间,跟踪函数本身可能会为不同的事件引入细微的时序差异,从而完全扭曲结果,使您的数据无法用于绝对时序比较。

在进行分析时,您在测量分析器对不同代码路径的 react 方式与您在测量代码路径本身一样多。当您想在复杂代码中精确定位何处时,您的所有执行时间都花在了这上面,这很好,但如果纯粹根据代码的执行速度来比较两段不同的代码,那就太糟糕了。

只剩下您的 timeit 结果,它们太接近了,无法调用。这两种方法的速度差不多。