我想使用它的函数式编程功能在 python 中构建一个 while 循环,但直到现在我都失败了。
我所完成的是代码的和平,它应该计算可被 1 到 20 的每个数字整除的最小数字。但它似乎并没有大量使用函数式编程功能。并且还给我如下错误:
"RuntimeError: maximum recursion depth exceeded" at the line of the incrementation of "i";
即使这应该限制在 20 个。
def byYmult(x, y): return x % y == 0
def first20div():
i=0
for y in range(1,20):
i += byYmult(x, y)
return i >= 20
def while_block():
global x
if first20div():
print(x)
return 1
else:
x += 1
return 0
x = 0
while_FP = lambda: ((not first20div()) and while_block() ) or while_FP()
while_FP()
请您参考如下方法:
由于很多原因,这是非功能性的:
- 你不传递,也不返回函数;
- 您只在底部构造一个命名的 lambda 表达式,但这通常被认为是非 Pythonic;
- 通常函数式编程意味着你不改变数据,但在这里你定义了一个你更新的
global x; - 一些全局变量也被视为非功能性的:所有数据都应传递给函数。
所以有很多工作要做。此外,您描述的算法不是最优的。与其执行我们一直猜测数字直到最终幸运的蛮力方法,更好的方法是计算数字 1..20 的最小公倍数 (LCM)。
我们可以首先定义 - 以函数方式 - 我们可以通过首先计算最大公约数 (GCD) 来计算 LCM,这可以通过 Euclidean Algorithm 来完成.幸运的是,它已经在 math 包中:
from math import gcd
现在LCM是:
def lcm(a,b):
return (a*b)//gcd(a,b)
可以通过计算前两个数字的 LCM 来计算三个或更多数字的 LCM,然后将其作为第一个参数传递给具有第三个数字的 LCM,或者更正式地说:
lcm(x,y,z) == lcm(lcm(x,y),z)
这可以通过使用 functools 中的 reduce 来完成:
from functools import reduce
def lcm_multiple(xs):
return reduce(lcm, xs)
现在我们可以通过传递一个 range(2,20) 对象来计算答案:
answer = lcm_multiple(range(2, 20))
或完整:
from math import gcd
from functools import reduce
def lcm(a,b):
return (a*b)//gcd(a,b)
def lcm_multiple(xs):
return reduce(lcm, xs)
answer = lcm_multiple(range(2, 20))
