阶乘递归中Python的可读性与效率
当我注意到这一点时,我正在玩弄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
导入时间
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)