rec_fn = lambda: 10==11 or rec_fn()
rec_fn()
我是Python新手并试图了解lambda表达式的工作原理。有人可以解释这种递归是如何工作的吗?我能够理解10 == 11将是'false',这就是rec_fn将被递归地再次调用的方式。
但是我无法得到的是这种看似新的编写lambda表达式的方法。
lambda x: x+y
发生了什么,参数'x'进入未命名的函数?
另外,为什么
rec_fn() = lambda: .... // a syntax error
rec_fn = lambda: .... //syntactically correct - WHY?
什么是rec_fn?它是函数还是变量?
答案 0 :(得分:4)
将函数调用视为运算符可能会有所帮助。因为它就是这样。当你做rec_fn()
时,你做了两件事。首先,您将获得对名为rec_fn
的对象的引用。这恰好是一个函数,但这并不重要(在Python中,函数之外的对象是可调用的)。然后有()
表示“调用我刚才命名的对象”。可以在不调用函数的情况下获取函数的引用,只需省略括号,然后就可以为它指定不同的名称,然后可以通过添加来调用它们。括号中。
def func1():
print "func1"
func2 = func1
func2() # prints "func1"
现在你可以看到lambda是如何工作的。
func3 = lambda x: x+1
您正在执行与上面func2 = func1
行相同的操作,除了lambda表达式 该函数。语法不同;可以定义lambda函数而不给它起名字。
Lambdas可以有任意数量的参数,因此lambda: 3
是一个不带参数且总是返回3的函数,而lambda x, y: x+y
是一个带有两个参数并返回其总和的函数。
关于or
的使用方式,它正在利用短路。基本上,or
知道如果它的第一个操作数是True
,它不需要评估第二个,因为无论第二个参数是什么,结果都将是True
。因此,您可以将其视为if not 10==11: rec_fn()
。顺便说一下,and
也会短路,但如果第一个参数是False
,它会这样做,因为它知道结果将是False
而不管第二个参数是什么。< / p>
答案 1 :(得分:0)
函数调用 - x()
- 是一个表达式。在赋值的左侧,它是一个合法的语法结构。应该怎么办? (它与说42 = lambda: ....
)
在第二种情况下,您只是将创建的新函数对象(使用lambda
关键字)分配给变量(名为rec_fn
)而不调用函数。
也许更明确的方法是使用(首选)非lambda嵌套函数方法:
# just for example, not really useful as it is unless you like to eat CPU
def rec_fn():
return 10 == 11 or rec_fn()
rec_fn()
lambda
关键字只是一个语法快捷方式,可用作表达式的一部分。
rec_fn
是局部变量(假设所述代码嵌套在函数/方法中)。 rec_fn
变量存储一个函数对象,以后可以使用()
调用它。方法大致相同(可以调用的函数),但它们是属性而不是变量。
答案 2 :(得分:0)
rec_fn = lambda: 10==11 or rec_fn()
rec_fn()
与此表达式类似,但是这个表达式需要一个参数
rec_fn = lambda x: 10==11 or rec_fn(x)
x = ...
rec_fn(x)
而你用rec_fn()调用一个没有参数的函数,因此没有x
rec_fn() = lambda: .... // a syntax error
这是试图将函数调用rec_fn()(右边有一个表达式)的结果设置为一个值。没有变量可以将lambda函数赋值给。
rec_fn = lambda: .... //syntactically correct - WHY?
这里rec_fn在包含lambda的变量中(实质上就像一个函数指针)
答案 3 :(得分:0)
rec_fn = lambda: 10==11 or rec_fn()
rec_fn()
在执行函数体之前,不会对其进行求值。一开始,rec_fn
没有任何价值。 lambda的内容只是一些在某个变量rec_fn
上有一些函数调用的表达式。它还不会失败,因为函数尚未执行。然后将新的lambda函数分配给变量rec_fn
,然后调用该函数。现在,由于函数正在执行,它将通过动作直到函数调用。表达式为10==11 or rec_fn()
。这是一个or
表达式,因此评估左侧。 10==11
为False因此它必须评估右侧,这是对某个函数(或其他可调用对象)rec_fn
的函数调用。此时,rec_fn
被分配给我们刚创建的函数(本身),因此它被调用(递归)。等等。它相当于:
def rec_fn():
return 10==11 or rec_fn()
可以根据需要使用尽可能多的参数编写Lambda。在lambda: ...
的情况下,没有指定,所以它是一个“不带参数的函数。”
请记住,函数(以及扩展名为lambdas)是第一类对象。您可以像任何其他对象一样传递它们并将它们存储到其他变量中。
rec_fn = lambda: ...
很好,因为你已经定义了一个lambda函数并将其存储到变量rec_fn
中。可以使用该名称rec_fn()
来调用它,就像使用任何其他函数一样。
rec_fn() = lambda: ...
另一方面,失败,因为您无法为函数调用rec_fn()
的结果分配任何内容。
以这种方式定义函数与正常函数定义有很大不同:
def rec_fn2(): # here you may use the parens with the name to indicate it takes no arguments
... # unlike in the lambda assignment above
试着记住差异。
答案 4 :(得分:0)
这可能是更容易理解的递归示例,因子lambda版本:
fact = lambda x: 1 if x == 0 else x*fact(x-1)
prin(fact(10))
输出:
3628800
请注意Python的递归限制。
使用或作为if..else:
的示例print 1 or 'a'
print 'a' or False
print False or True or 0/9
fact_or = lambda x: x == 0 and 1 or x * fact_or(x-1)
print fact_or(10)