python filter函数
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)
for n in primes():
if n<1000:
print(n)
else:
break
程序是输出质数,但是看这个程序始终不明白
it=filter(_not_divisible(n),it)
这里函数加了括号有n,怎么之前用filter都没加呢?
比如这个
def not_empty(s):
return s and s.strip()
list(filter(not_empty, ['A', '', 'B', None, 'C', ' ']))
另外这个
def _not_divisible(n):
return lambda x: x % n > 0
x的值是怎么传进去的呢?
it=filter(_not_divisible(n),it)
这个是挨个吧it里面的数等于n,然后运行函数,那x应该是等于剩余的it,没有哪里赋值了啊?
还有filter会作用于每一个it里面的元素,it是个生成器,还是无限大的,我觉得程序运行一遍就会无限循环,外面怎么还能不断while True呢?
其他问题都清楚了,可是filter碰到无限的生成器,还不断循环filter,就不明白了,可否这样理解:
程序执行第一次,返回2,第二次,返回3,第三次,开始执行 it=filter(_not_divisible(n),it),这里n还是3, 这里filter函数并没有把it里的无穷多个数算一遍,他只是记住了,后续如果碰到能被3整除的数要筛掉,然后next返回5,第4次返回...,第五次it里面碰到9了,然后根据之前‘嵌套’的规则,9被筛掉了。
就是不是执行一次 it=filter(_not_divisible(n),it),就把it里所有的数过了一遍,他实际上什么也没做,只是记住了这个方法,在n=next(it)的时候才会用it里的下一个数执行,并且碰到应该筛掉的自动筛掉并执行下一个it里的数
对吗?
另外还有个小问题,我把函数改一下
it=filter(lambda x : x%n>0 ,it)
怎么返回就是直接是所有的奇数了呢? 展开
不会死循环,生成器是个虚拟抽象的概念,你可以认为_odd_iter() primes() 里面运行的时候
python解释器并不生成实际的List,也就不会耗费内存和时间
真正分配给List内存只在以下过程, primes()这个生成器是逐步分配内存的!!
for n in primes():
if n<1000:
print(n)
else:
break
另外提醒你下,你的程序只能在Python 3.x版本下正确运行:-)因为你用的是 filter返回生成器对象的用法!!如果你要你的程序在Python 2.x正确运行,需改成如下形式。
根据你最新的追问,“为什么it=filter(lambda x : x%n>0 ,it)不行??“直接在filter里用Lambda表达式是完全可以的,你的原因是你的Lambda表达式漏输入了一个n,请看如下形式.
# Python 2.x下需导入itertools库的ifilter才能和python 3.x的filter等效
import itertools
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=itertools.ifilter(_not_divisible(n),it)
it = itertools.ifilter(lambda x, n=n: x%n > 0, it)
for n in primes():
if n<1000:
print(n)
else:
break
这里函数加了括号有n,怎么之前用filter都没加呢?
因为这里是以参数n调用函数_not-divisible(n),用的是其返回值
def _not_divisible(n):
return lambda x: x % n > 0
x的值是怎么传进去的呢?,x的值不用传进去,这个函数直接返回一参数名为x的匿名函数,
如果it=filter(_not_divisible(5),it),等同于it=filter(lambda x:x%5>0,it)
it=filter(_not_divisible(n),it)
将it中元素依次作为参数,判断lambda x:x%n>0返回值的真假,返回it中所有 %n大于0的元素
it=filter(_not_divisible(n),it),filter里的it是迭代it里的所有元素,没有限制,应该会无限循环,用python 2.7运行 的结果也是输出2,3后不动了
关于it=filter(_not_divisible(n),it) , 函数加不加括号只是表象,你应该说第一个参数应该是一个函数,是这个意思不? 你自己看_not_divisible(n)的定义,它return一个lambda函数.理解了吗?
def _not_divisible(n):
return lambda x: x % n > 0
关于x的值怎么传进去,你看看Python基础里lambda函数怎么用,就理解了
3. 为什么外面加while True,你问这个问题说明你有2个地方没弄明白,一是python程序基本的运行流程,哪个先运行,哪个后运行,这个顺序,流程,结构你没搞明白, 还有生成器你也没搞明白怎么回事
建议先把python基础打牢,网上的说法基本上都是python简单易学,但是任何一门语言到了一定的程序都不是那么容易,基础不牢,基本概念不搞清楚,没法深入,永远都只能写写十几行的脚本