Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/321.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_Recursion_Factorial_Readability - Fatal编程技术网

阶乘递归中Python的可读性与效率

阶乘递归中Python的可读性与效率,python,recursion,factorial,readability,Python,Recursion,Factorial,Readability,当我注意到这一点时,我正在玩弄python中不同的递归方法: [为方便起见简化] 导入时间 def fac(n): 如果[0,1]中有n: 返回1 其他: 返回n*fac(n-1) def fac2(n): 总计=1 如果n==0: 返回总数 其他: 返回n*fac2(n-1) t0=时间。时间() 外交事务委员会(997) t1=时间。时间() 打印(t1-t0) t3=时间。时间() fac2(997) t4=时间。时间() 打印(t4-t3) >>> 0.00124359130859375

当我注意到这一点时,我正在玩弄python中不同的递归方法:

[为方便起见简化]

导入时间
def fac(n):
如果[0,1]中有n:
返回1
其他:
返回n*fac(n-1)
def fac2(n):
总计=1
如果n==0:
返回总数
其他:
返回n*fac2(n-1)
t0=时间。时间()
外交事务委员会(997)
t1=时间。时间()
打印(t1-t0)
t3=时间。时间()
fac2(997)
t4=时间。时间()
打印(t4-t3)
>>> 0.00124359130859375
>>> 0.00046324729919433594
我知道,
时间
实际上并不能测量速度,但这些函数之间的差异(可以说可以忽略不计)有整整一个数量级

我觉得
fac2()
看起来更漂亮,更容易阅读,但我应该避免它,因为声明一个新的var可能会非常昂贵吗

提前谢谢你


编辑: 谢谢你的回复!(是的,我在说
fac()
更快时犯了一个错误)我从回答中得到了建议,并拨打了专一电话:

导入时间
def fac(n):
如果[0,1]中有n:
返回1
其他:
返回n*fac(n-1)
def fac2(n):
总计=1
如果n==0:
返回总数
其他:
返回n*fac2(n-1)
def fac3(n):
如果n<2:
返回1
其他:
返回n*fac(n-1)
def fac4(N,m=0):
如果m==N:
返回最大值(1,N)
h=(N+m)//2
返回fac4(h,m)*fac4(N,h+1)
打印('fac1:',end='')
t0=时间。时间()
对于范围(1000)内的i:
外交事务委员会(997)
t1=时间。时间()
打印(t1-t0)
打印('fac2:',end='')
t3=时间。时间()
对于范围(1000)内的i:
fac2(997)
t4=时间。时间()
打印(t4-t3)
打印('fac3:',end='')
t5=时间。时间()
对于范围(1000)内的i:
fac3(997)
t6=时间。时间()
打印(t6-t5)
打印('fac4:',end='')
t7=时间。时间()
对于范围(1000)内的i:
fac4(997)
t8=时间。时间()
打印(t8-t7)
这大约是我运行程序一段时间后得到的平均值(WSL2 Ubuntu 18.04):

现在,我很想知道为什么
fac3()
似乎是其中“最快的”。有人能解释一下原因吗


再次感谢您,请提前告知。

更漂亮的做法是使用
n您的测量方法是误导性的:

单个函数的执行并不能说明什么:分页、编译等的成本会对结果产生重大影响。当执行函数的次数较多时,这种一次性效果的影响可以减小

以以下方式包装对不同的
fac
函数的调用时:

t0 = time.time()
for i in range(10000):
    fac(997)
t1 = time.time()
print(t1-t0)
然后差异在3%的范围内-至少在我的系统上。基于这些微小差异的设计更改是不可取的-这些差异很容易是由于不在代码中的原因造成的(跨越缓存页边界等)

结论:

  • 通常最好是可读性
  • 在性能重要的地方,进行相应的测量和优化是可以的。然而,正如您的示例所示,获得可靠且有意义的测量数据并非易事
  • 不同解决方案之间的性能差异越小,您就越需要了解差异的真正原因并排除环境的影响

你让它听起来像是
fac2
是较慢的一个…这个结果在许多不同的测试中重复吗?无论如何,您的测试实际上显示,
fac2
速度更快(大约是3倍,所以大约是“数量级”的一半),这与您的文本相反。我不知道这是否通常是真的,或者如果是真的,为什么-但我想这是一个事实,在[0,1]
检查中,对
执行了两个相等操作,而不仅仅是检查
n
是否为0。我发现使用
timeit
timeit.timeit(lambda:fac(997),number=100)可以忽略不计
给出
0.04686011300001036
timeit.timeit(lambda:fac2(997),number=100)
给出
0.044798477000005
。。。不近人情magnitude@RobinZigmond我认为“瓶颈”是创建列表,而不是检查中的
,但最好使用profiler@DeepSpace窥视孔优化器使它成为一个常量元组,它只在实际字节码中引用它,即
2 LOAD_CONST 1((0,1))
def fact(N,m=0):
    if m==N: return max(1,N)
    h = (N+m)//2
    return fact(h,m)*fact(N,h+1)
t0 = time.time()
for i in range(10000):
    fac(997)
t1 = time.time()
print(t1-t0)