Python新手求问,关于lambda表达式的问题

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

def main(): for n in primes(): if n < 100: print(n) else: break

def _odd_iter(): n = 1 while True: n = n + 2 yield n

def _not_divisible(n): return lambda x: x % n > 0

def primes(): yield 2 it = _odd_iter() while True: n = next(it) yield n it = filter(_not_divisible(n), it)

if name == ‘main’: main()

如果将

it = filter(_not_divisible(n), it)

改成

it = filter(lambda x: x % n > 0, it)

两次结果不一样,是 n 的作用域问题? filter 惰性求值问题?


Python新手求问,关于lambda表达式的问题

15 回复

首先说明下,题主的代码参数有点问题哦

其次,
_not_divisible 函数你这样写返回时的一个 function,function 永远是 True
直接写 lambda 返回的是 True 或者 False

filter 内置函数对 True 结果处理,这应该就是问题所在

最后,
看下面代码,题主参考下应该就明白了

def _not_divisible(n):
return lambda x: x % 3 > 0

filter(_not_divisible, [5,6])
[5, 6]

_not_divisible(5)
<function <lambda> at 0x036DAA30>
_not_divisible(6)
<function <lambda> at 0x036F82F0>

上面这两个都返回的是 function

filter(lambda x: x % 3 > 0, [5,6])
[5]

f = lambda x: x % 3 > 0
filter(f, [5,6])
[5]

f(5)
True
f(6)
False

这个有 False 返回

题主明白了吗?


lambda表达式就是用来创建匿名函数的,简单说就是没有名字的小函数。

比如你想写个函数把数字加10,正常写法是:

def add_ten(x):
    return x + 10

用lambda可以写成一行:

add_ten = lambda x: x + 10

它最常用的地方是配合sortmapfilter这些函数。比如按字符串长度排序:

words = ["apple", "bee", "cat"]
words.sort(key=lambda w: len(w))
print(words)  # ['cat', 'bee', 'apple']

或者用map给列表每个数平方:

nums = [1, 2, 3]
squared = list(map(lambda x: x**2, nums))
print(squared)  # [1, 4, 9]

记住lambda只能写一行表达式,复杂的逻辑还是用def定义普通函数。

一句话建议:lambda适合写简单的一次性操作函数。

回复里不会贴代码,看起来有点乱,将就看吧,微笑脸

你看错了
用了 python 好多年了,我也搞不懂,坐等高手,我感觉是不是跟下面这个有关:
1:
for i in range(5):
f=lambda x:x+i
i=5
print f(1)
output:
6
6
6
6
6

2:
def aaa(n):
return lambda x:x+n

for i in range(5):
f=aaa(i)
i=5
print f(1)
output:
1
2
3
4
5

我觉得有可能是这样子的:
如果用 it = filter(lambda x: x % n > 0, it)的话,在使用 next(it)的时候,才会去找当前的 n,不管你之前过滤了多少次,等于用当前的 n 过滤了同样多次。
如果用 it = filter(_not_divisible(n), it)的话,会把每次过滤的 n 记录下来,所以就会成功输出所有素数了。
具体看上一层楼的例子。


应该只有这个解释了。

如果用 it = filter(lambda x: x % n > 0, it)的话,比如说,next(it)要输出 5 的时候,会用 3 来过滤,如果 next(it)要输出 7 的话,就用 5 来过滤 2 次(当然和过滤 1 次一样),接下来输出 9,用 7 过滤,所以这样做等于把所有奇数都输出出来了。

其实就是 1 楼说的问题
你改成 lambda n: lambda x: x % n > 0 试试


什么鬼。。

lambda 的返回值和 def 一样是个函数

it 会形成嵌套的 generator,lambda 中 n 是引用(所以会变,都是同一个),而经过函数的 n 会被拷贝一份放闭包里。

回复里可以 Gist


filter 第一个参数是函数,_not_divisible(n) 是函数, lambda x: x % n > 0 也是函数,这个参数没问题


如果要这样改的话,应该改成:(lambda n: lambda x: x % n > 0)(n)

赞同使用函数形成闭包的解析。直接使用 lambda 表达式是无法形成闭包的

回到顶部