Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Python中阶乘函数的尾部递归版本如此缓慢?_Python_Performance_Recursion_Tail Recursion - Fatal编程技术网

为什么Python中阶乘函数的尾部递归版本如此缓慢?

为什么Python中阶乘函数的尾部递归版本如此缓慢?,python,performance,recursion,tail-recursion,Python,Performance,Recursion,Tail Recursion,我试图比较不同实现的阶乘函数的运行时间。然而,我发现阶乘函数的尾部递归版本比迭代版本和非尾部递归版本慢得多,我无法对此做出解释。 这是我的代码实现。我正在使用Python 3.7.4测试代码 import sys from line_profiler import LineProfiler sys.setrecursionlimit(20000) def fact_iter(n): """Return the factorial of n, using iteration"""

我试图比较不同实现的阶乘函数的运行时间。然而,我发现阶乘函数的尾部递归版本比迭代版本和非尾部递归版本慢得多,我无法对此做出解释。 这是我的代码实现。我正在使用Python 3.7.4测试代码

import sys
from line_profiler import LineProfiler
sys.setrecursionlimit(20000)


def fact_iter(n):
    """Return the factorial of n, using iteration"""
    product = 1
    for i in range(2, n + 1):
        product *= i
    return product


def fact_non_tail_recur(n):
    """Return the factorial of n, using non-tail recursion"""
    if n == 1:
        return 1
    product = n * fact_non_tail_recur(n - 1)
    return product


def fact_tail_recur(n, product=1):
    """Return the factorial of n, using tail recursion"""
    if n == 1:
        return product
    product *= n
    return fact_tail_recur(n - 1, product)


def fact_tail_recur_2(n, i=1, product=1):
    if i == n:
        return product * i
    product *= i
    return fact_tail_recur_2(n, i+1, product)


def profile(f):
    lp = LineProfiler()
    lp_wrapper = lp(f)
    lp_wrapper(10000)
    lp.print_stats()


if __name__ == '__main__':
    profile(fact_iter)
    profile(fact_non_tail_recur)
    profile(fact_tail_recur)
    profile(fact_tail_recur_2)
下面是函数的运行时间配置文件

Timer unit: 1e-06 s

Total time: 0.040521 s
File: fact.py
Function: fact_iter at line 6

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     6                                           def fact_iter(n):
     7                                               """Return the factorial of n, using iteration"""
     8         1          2.0      2.0      0.0      product = 1
     9     10000      13513.0      1.4     33.3      for i in range(2, n + 1):
    10      9999      27005.0      2.7     66.6          product *= i
    11         1          1.0      1.0      0.0      return product

Timer unit: 1e-06 s

Total time: 0.042846 s
File: fact.py
Function: fact_non_tail_recur at line 14

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
    14                                           def fact_non_tail_recur(n):
    15                                               """Return the factorial of n, using non-tail recursion"""
    16     10000      13389.0      1.3     31.2      if n == 1:
    17         1          2.0      2.0      0.0          return 1
    18      9999      16481.0      1.6     38.5      product = n * fact_non_tail_recur(n - 1)
    19      9999      12974.0      1.3     30.3      return product

Timer unit: 1e-06 s

Total time: 0.085538 s
File: fact.py
Function: fact_tail_recur at line 22

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
    22                                           def fact_tail_recur(n, product=1):
    23                                               """Return the factorial of n, using tail recursion"""
    24     10000      13812.0      1.4     16.1      if n == 1:
    25         1          2.0      2.0      0.0          return product
    26      9999      55390.0      5.5     64.8      product *= n
    27      9999      16334.0      1.6     19.1      return fact_tail_recur(n - 1, product)

Timer unit: 1e-06 s

Total time: 0.07916 s
File: fact.py
Function: fact_tail_recur_2 at line 30

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
    30                                           def fact_tail_recur_2(n, i=1, product=1):
    31     10000      13521.0      1.4     17.1      if i == n:
    32         1         12.0     12.0      0.0          return product * i
    33      9999      49390.0      4.9     62.4      product *= i
    34      9999      16237.0      1.6     20.5      return fact_tail_recur_2(n, i+1, product)
由timeit测量的运行时间图


FWIW,Python没有TCO。如果从
product=1
中删除
=1
会发生什么?是的,确实如此,所以我希望尾部递归的运行时间将接近非尾部递归。它无法解释它们之间可测量的运行时间差异。只是好奇,你是在寻找最快的方法来获得阶乘还是解释不同方法的“幕后”情况?“这是一个好问题,也是一个有趣的问题。”MateenUlhaq说,没有什么大的区别。