函数式python——为什么这些生成器中只有一个需要list()才能工作?
从元组向量(剩余、模)计算中国剩余定理时,以下代码失败:函数式python——为什么这些生成器中只有一个需要list()才能工作?,python,functional-programming,chinese-remainder-theorem,Python,Functional Programming,Chinese Remainder Theorem,从元组向量(剩余、模)计算中国剩余定理时,以下代码失败: c = ((1,5),(3,7),(11,13),(19,23)) def crt(c): residues, moduli = zip(*c) N = product(moduli) complements = (N/ni for ni in moduli) scaled_residues = (product(pair) for pair in zip(residues
c = ((1,5),(3,7),(11,13),(19,23))
def crt(c):
residues, moduli = zip(*c)
N = product(moduli)
complements = (N/ni for ni in moduli)
scaled_residues = (product(pair) for pair in zip(residues,complements))
inverses = (modular_inverse(*pair) for pair in zip(complements,moduli))
si = (product(u) for u in zip(scaled_residues,inverses))
result = sum(si) % N
return result
将结果设为0(我猜生成的iterables是空的)。然而,以下代码工作得非常完美:
def crt(c):
residues, moduli = zip(*c)
N = product(moduli)
complements = list((N/ni for ni in moduli)) # <-- listed
scaled_residues = (product(pair) for pair in zip(residues,complements))
inverses = (modular_inverse(*pair) for pair in zip(complements,moduli))
si = (product(u) for u in zip(scaled_residues,inverses))
result = sum(si) % N
return result
def crt(c):
剩余物,模量=zip(*c)
N=乘积(模数)
complements=list((N/ni表示模中的ni))#您在complements上迭代了两次。只能在生成器表达式上迭代一次
如果您使用的是Python2.x,zip(剩余,补充)
将消耗complements
,而zip(补充,模块)
将一无所有。在Python3.x上,zip
本身就是一个生成器,当sum()
实际运行生成器时,问题会出现在代码的后面。每次迭代都会从补遗中提取两个项目。根据答案中的建议,我重新实现了问题中的代码,如下所示:
def complements(moduli,N):
return (N/ni for ni in moduli)
def scaled_residues(residues,complements):
return (product(pair) for pair in zip(residues,complements))
def inverses(complements,moduli):
return (modular_inverse(*pair) for pair in zip(complements,moduli))
def crt_residue_terms(scaled_residues,inverses):
return (product(u) for u in zip(scaled_residues,inverses))
def crt(c):
residues, moduli = zip(*c)
N = product(moduli)
return sum(
crt_residue_terms(
scaled_residues(residues,complements(moduli,N)),
inverses(complements(moduli,N),moduli)
)) % N
现在,它不使用任何列表即可生成正确的8851结果。酷。我喜欢你关于python的问题!这可能是同样的问题吗?也许你可以先打印zip(剩余,补码)
,然后在迭代之前打印zip(补码,模)
。@AlexL好的,我会试试。我认为最好写[N/ni代表模中的ni]
而不是列表((N/ni代表模中的ni))
Boom!就这样!我忘了发电机的事了。生成器的单次使用质量是否与其他函数式语言中的生成器相同…可能是Scala或Haskell?在后面的代码中,您的意思是什么?zip也是生成器?我猜这就是函数式编程被称为函数式编程的原因。如果我将上面的函数分解成更小的函数,而不是将生成器分配给变量,那么函数可以在需要时调用生成器,并且不会出现穷举。请注意,与流行的观点相反,生成器表达式并不总是比列表更有效。“如果你在小集合上迭代,通常内存的权衡是不值得的。”PauloScardine指出。我相信你。