python lambda 判断_在Python的Filter中使用lambda函数时,为何达不到预期效果?

最近我在学习python的时候也遇到了同样的问题,碰巧看到了这个提问,还是挺有缘分的。

先说结论:直接使用lambda表达式时filter(lambdax:x%n>0, it),n会随着代码的运行而改变,导致filter函数在运行时出现错误。

具体分析过程:

1、本来想直接看filter函数的源码,但是因为自己是新手,一直找不到位置,而且看到有人讲有些内置函数是使用c语言来编写的,遂放弃。

2、开始自己写测试代码,思路很简单,就是看使用lambda表达式的时候,filter函数如何调用的。

首先看正确的情况下:

def test():

mylist=(x for x in range(2,10))

while True:

n=next(mylist)

#fnc=lambda x: x % n > 0

def fnc(x,n=n):

print("filter调用方法%d/%d结果为%s"%(x,n,x%n>0))

return x%n>0

yield n

mylist=filter(fnc,mylist)

for m in test():

print("-----遍历到%s"%m)

结果为:正常调用的结果,最后出现异常是因为生成器内容结束

不正常情况的代码就改了一行:def fnc(x,n=n):改为def fnc(x):

结果为:

可以很清楚的对比到:不正常的情况下,filter方法调用的表达式x % n > 0时,n都为一个值,而正常情况下则是调用的不同值。

其原因正是因为上文所提到的:直接使用lambda表达式时filter(lambdax,x%n>0, it),n会随着代码的运行而改变,导致filter函数在运行时出现错误。而使用filter(lambdax,n=n:x%n>0, it)时,n是复制一份到了filter方法中保存起来,后面n的改变不会修改此时的值。

3、为什么会有这样的结果呢?

首先通过python的help函数来查看filter的描述:

看起来有点不太明白,没关系,搜索一下中文版:filter(function,iterable)用 iterable 中函数 function 返回真的那些元素,构建一个新的迭代器。iterable 可以是一个序列,一个支持迭代的容器,或一个迭代器。如果 function 是 None ,则会假设它是一个身份函数,即 iterable 中所有返回假的元素会被移除。

请注意, filter(function, iterable) 相当于一个生成器表达式,当 function 不是 None 的时候为 (item for item in iterable if function(item));function 是 None 的时候为 (item for item in iterable if item) 。

filter函数的返回值是一个可迭代对象

filter在实现时采用了迭代器技术,将计算延迟到对filter函数返回结果进行遍历时才进行。就是filter函数返回的是一个迭代器,不是列表,在使用的时候才会计算,所以才会出现上面运行所得出的:调用值时才会计算,比如遍历到2之后再继续调用生成器,才会计算3%2是否有余数,返回true证明3可以,即输出3。注意后面的过滤过程中会调用每个n值不同的方法,具体实现没有源码我也不太懂,也没有搜索到相应的讲解。

4、回到廖雪峰的python教程:

在本章的函数式编程-返回函数一节中有明确提到:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值