Python 职能组成

Python 职能组成,python,function,lambda,printing,Python,Function,Lambda,Printing,两个打印语句都给出了答案83,但我不明白答案是如何得出的。有谁能告诉我这两个词的区别吗?这两个词唯一的区别是一对毫无意义的括号,所以它们给出的答案当然是一样的。这与问这两者之间的区别是一样的: 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)) math.abs(2) (math.abs)(

两个打印语句都给出了答案83,但我不明白答案是如何得出的。有谁能告诉我这两个词的区别吗?

这两个词唯一的区别是一对毫无意义的括号,所以它们给出的答案当然是一样的。这与问这两者之间的区别是一样的:

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))
math.abs(2)
(math.abs)(2)
或者,更妙的是(多亏奥利维尔·梅隆指出了这一点),这两者之间的区别:

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))
math.abs(2)
(math.abs)(2)
实际上,没有区别。解析它们的第一步有点不同,但它们最终使用相同的AST,因此使用相同的字节码,因此使用相同的行为


相反,您可能想问以下问题:

1 + 2
(1) + 2
这是一个很大的区别

在第一个函数中,我们在lambda上调用了三次
,因此它给了我们一个函数,这个函数加3,然后加3,再加3,最后加9。然后我们三次调用
,它给我们一个函数,加9,再加9,再加9,再加27。然后我们把它叫做2,当然是29

在第二个函数中,我们在
上调用了
三次
,因此它给了我们一个三次调用的函数,执行我们要求它执行的任何操作3**3(27)次。然后我们把它叫做lambda,它加了3,37倍,也就是说它加了81倍。然后我们称之为2,得到83

如果将
三次
三次(三次)
应用于
lambda x:x+1
而不是
lambda x:x+3
,这样就不会混淆这些单独的3,并且如果在0而不是2上调用最后一个函数,那么可能会比较容易混淆


对于大多数函数,您不能因为编写这样的内容而感到困惑,一个版本或另一个版本将是一个简单的
TypeError
。(试着写
math.fabs(math.fabs)
,或者
int(int)
,看看会发生什么。)是什么让
三次
如此特别


那么,考虑一下
的类型三次。你给它任何一个
A->A
类型的函数(也就是说,它接受某个
A
类型的值,并返回同一个
A
类型的值),然后它返回另一个
A->A
类型的函数。但这意味着它本身就是一个类型为
a->a
的函数,因此您可以自己调用它。这是一件让人兴奋不已的事情,直到你想到它的类型,但一旦你做了,就没什么令人兴奋的了

两者之间的唯一区别是一对无意义的括号,因此它们给出的答案当然是相同的。这与问这两者之间的区别是一样的:

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))
math.abs(2)
(math.abs)(2)
或者,更妙的是(多亏奥利维尔·梅隆指出了这一点),这两者之间的区别:

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))
math.abs(2)
(math.abs)(2)
实际上,没有区别。解析它们的第一步有点不同,但它们最终使用相同的AST,因此使用相同的字节码,因此使用相同的行为


相反,您可能想问以下问题:

1 + 2
(1) + 2
这是一个很大的区别

在第一个函数中,我们在lambda上调用了三次
,因此它给了我们一个函数,这个函数加3,然后加3,再加3,最后加9。然后我们三次调用
,它给我们一个函数,加9,再加9,再加9,再加27。然后我们把它叫做2,当然是29

在第二个函数中,我们在
上调用了
三次
,因此它给了我们一个三次调用的函数,执行我们要求它执行的任何操作3**3(27)次。然后我们把它叫做lambda,它加了3,37倍,也就是说它加了81倍。然后我们称之为2,得到83

如果将
三次
三次(三次)
应用于
lambda x:x+1
而不是
lambda x:x+3
,这样就不会混淆这些单独的3,并且如果在0而不是2上调用最后一个函数,那么可能会比较容易混淆


对于大多数函数,您不能因为编写这样的内容而感到困惑,一个版本或另一个版本将是一个简单的
TypeError
。(试着写
math.fabs(math.fabs)
,或者
int(int)
,看看会发生什么。)是什么让
三次
如此特别


那么,考虑一下
的类型三次。你给它任何一个
A->A
类型的函数(也就是说,它接受某个
A
类型的值,并返回同一个
A
类型的值),然后它返回另一个
A->A
类型的函数。但这意味着它本身就是一个类型为
a->a
的函数,因此您可以自己调用它。这是一件让人兴奋不已的事情,直到你想到它的类型,但一旦你做了,就没什么令人兴奋的了

你来自列表语言?如果结果是匹配的,则括号数之间的差异这两者之间的唯一区别是,第二个括号在第一个
周围有一对无意义的额外括号。我不知道如何在不抛弃AST或其他东西的情况下更深入地解释这一点,但这是非常琐碎的。你认为有什么不同?正如abarnert所说的,偏执狂是超级的,而且两行都是一样的。我认为这里隐藏着一个很好的问题,你只是问得不对。我试着回答这个问题以及你实际问的问题。如果您仍然感到困惑,请告诉我什么是困惑,我可能可以改进它。您来自列表语言?如果结果是匹配的,则括号数之间的差异这两者之间的唯一区别是,第二个括号在第一个
周围有一对无意义的额外括号。我不知道如何在不抛弃AST或其他东西的情况下更深入地解释这一点,但这是非常琐碎的。你认为有什么不同?正如abarnert所说的,偏执狂是超级的,两条线都是一样的。我认为实际上有一个很好的问题埋在我的心里