功能的组成

时间:2018-03-12 06:50:41

标签: python function lambda printing

def thrice(f):
    return lambda x: f(f(f(x)))
print(thrice(thrice)(lambda x: x+3)(2))
print((thrice)(thrice)(lambda x: x+3)(2))

两个印刷语句都给出了答案83,但我不明白答案是如何得出的。任何人都可以告诉我两者之间的区别吗?

1 个答案:

答案 0 :(得分:3)

两者之间的唯一区别是一对无意义的括号,所以当然它们给出了相同的答案。这与要求这两者之间的差异是一样的:

math.abs(2)
(math.abs)(2)

或者,甚至更好(感谢OlivierMelançon指出这一点),这两者之间存在差异:

1 + 2
(1) + 2

实际上,没有区别。解析它们的第一步有点不同,但它们最终得到相同的AST,因此字节码相同,因此行为相同。

你可能想要问一下:

>>> thrice(thrice(lambda x: x+3))(2)
29
>>> thrice(thrice)(lambda x: x+3)(2)
83

这是一个很大的不同。

在第一个中,我们在lambda上调用thrice,所以它给我们一个函数,它增加3,然后加3,然后加3,所以它增加9.然后我们调用{{ 1}},所以它给了我们一个函数,它增加9,然后加9,然后加9,所以它增加了27.然后我们在2上调用它,当然得到29。

在第二个问题中,我们在thrice上调用thrice,因此它为我们提供了三重函数的功能,无论我们要求它做什么3 ** 3(27)次。然后我们在lambda上调用它,所以它增加了3,37次,这意味着它增加了81.然后我们在2上调用它,得到83.

如果您将thricethrice应用于thrice(thrice)而不是lambda x: x+1,那么可能不那么令人困惑,因此您不会将这些单独的3混淆,如果您将最终函数调用0而不是2。

对于大多数功能,你不能通过编写类似的东西来混淆自己 - 一个版本或另一个版本将是一个简单的lambda x: x+3。 (尝试撰写TypeErrormath.fabs(math.fabs),看看会发生什么。)是什么让int(int)如此特别?

好吧,想想thrice的类型。你给它任何类型为thrice的函数(也就是说,它接受某种类型A->A的值并返回相同类型A的值),并返回另一个类型的函数A。但这意味着它本身就是A->A类型的函数,所以你可以自己调用它。这是看起来真正令人兴奋的事情之一,直到你想到这些类型,但是一旦你做到这一点,那就没那么令人兴奋了。 "No, John, you are the type theory!" And then John was a Haskell.