1、map

语法:

map(func,Iterable)

map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。

>>> def f(x):
... return x * x
...
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]

map()传入的第一个参数是f,即函数对象本身。由于结果r是一个Iterator,Iterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list。

>>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
['1', '2', '3', '4', '5', '6', '7', '8', '9']

2、reduce

reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
比方说对一个序列求和,就可以用reduce实现:
>>> from functools import reduce
>>> def add(x, y):
... return x + y
...
>>> reduce(add, [1, 3, 5, 7, 9])
25

当然求和运算可以直接用Python内建函数sum(),没必要动用reduce。
但是如果要把序列[1, 3, 5, 7, 9]变换成整数13579,reduce就可以派上用场:
>>> from functools import reduce
>>> def fn(x, y):
... return x * 10 + y
...
>>> reduce(fn, [1, 3, 5, 7, 9])
13579

这个例子本身没多大用处,但是,如果考虑到字符串str也是一个序列,对上面的例子稍加改动,配合map(),我们就可以写出把str转换为int的函数:
>>> from functools import reduce
>>> def fn(x, y):
... return x * 10 + y
...
>>> def char2num(s):
... return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
...
>>> reduce(fn, map(char2num, '13579'))
13579
整理成一个str2int的函数就是:
from functools import reduce
def str2int(s):
  def fn(x, y):
    return x * 10 + y
  def char2num(s):
    return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
  return reduce(fn, map(char2num, s))
还可以用lambda函数进一步简化成:

from functools import reduce
def str2int(s):
  # def fn(x, y):
  # return x * 10 + y
  def char2num(s):
    return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
  # return reduce(fn, map(char2num, s))
  return reduce(lambda x, y: x * 10 + y, map(char2num, s))

也就是说,假设Python没有提供int()函数,你完全可以自己写一个把字符串转化为整数的函数,而且只需要几行代码!

3、filter过滤器

Python内建的filter()函数用于过滤序列。
和map()类似,filter()也接收一个函数和一个序列。和map()不同的时,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。

例如,在一个list中,删掉偶数,只保留奇数,可以这么写:
def is_odd(n):
  return n % 2 == 1
list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
# 结果: [1, 5, 9, 15]
把一个序列中的空字符串删掉,可以这么写:
def not_empty(s):
return s and s.strip()
list(filter(not_empty, ['A', '', 'B', None, 'C', ' ']))
# 结果: ['A', 'B', 'C']
可见用filter()这个高阶函数,关键在于正确实现一个“筛选”函数。
注意到filter()函数返回的是一个Iterator,也就是一个惰性序列,所以要强迫filter()完成计算结果,需要用list()函数获得所有结果并返回list。

问题:求素数

计算素数的一个方法是埃氏筛法,它的算法理解起来非常简单:
首先,列出从2开始的所有自然数,构造一个序列:
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...
取序列的第一个数2,它一定是素数,然后用2把序列的2的倍数筛掉:
3, , 5, , 7, , 9, , 11, , 13, , 15, , 17, , 19, , ...
取新序列的第一个数3,它一定是素数,然后用3把序列的3的倍数筛掉:
5, , 7, , , , 11, , 13, , , , 17, , 19, , ...
取新序列的第一个数5,然后用5把序列的5的倍数筛掉:
7, , , , 11, , 13, , , , 17, , 19, , ...
不断筛下去,就可以得到所有的素数。

用Python来实现这个算法,可以先构造一个从3开始的奇数序列:
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) # 构造新序列

这个生成器先返回第一个素数2,然后,利用filter()不断产生筛选后的新的序列。
由于primes()也是一个无限序列,所以调用时需要设置一个退出循环的条件:

# 打印1000以内的素数:
for n in primes():
  if n < 1000:
  print(n)
else:
  break
注意到Iterator是惰性计算的序列,所以我们可以用Python表示“全体自然数”,“全体素数”这样的序列,而代码非常简洁。

总结:

filter()的作用是从一个序列中筛出符合条件的元素。由于filter()使用了惰性计算,所以只有在取filter()结果的时候,才会真正筛选并每次返回下一个筛出的元素。

python的map、reduce和filter(过滤器)函数(廖雪峰老师python基础)的更多相关文章

  1. 【廖雪峰老师python教程】——filter/sorted

    filter Python内建的filter()函数用于过滤序列. 和map()类似,filter()也接收一个函数和一个序列.和map()不同的是,filter()把传入的函数依次作用于每个元素,然 ...

  2. 廖雪峰老师Python教程读后笔记

    廖老师网站:http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000 花几天时间看了廖老师的 ...

  3. 【廖雪峰老师python教程】——map/reduce

    Map[单个操作对不同单一对象重复进行] map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回. 返回结果注 ...

  4. python 协程(单线程中的异步调用)(转廖雪峰老师python教程)

    协程,又称微线程,纤程.英文名Coroutine. 协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用. 子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在 ...

  5. 【廖雪峰老师python教程】——进程与线程

    多进程 操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒……这样反复执行下去.表面上看,每个任务都是交替执行的,但是,由于CPU ...

  6. 【廖雪峰老师python教程】——IO编程

    同步IO 异步IO 最常见的IO——读写文件 读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一 ...

  7. 【廖雪峰老师python教程】——OOP

    概述 面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 数据封装.继承和多态 ...

  8. 【廖雪峰老师python教程】——模块

    使用模块 任何模块代码的第一个字符串都被视为模块的文档注释: 使用__author__变量把作者写进去,这样当你公开源代码后别人就可以瞻仰你的大名: 当我们在命令行运行模块文件时,Python解释器把 ...

  9. 【廖雪峰老师python教程】——装饰器

    装饰器 # 一个函数装饰器的列子 def log(func): def wrapper(*args,**kwargs): print('Name=%s'%func.__name__) return f ...

随机推荐

  1. WEB安全----XSS和CSRF

    随着Web2.0.社交网络.微博等等一系列新型的互联网产品的诞生,基于Web环境的互联网应用越来越广泛,企业信息化的过程中各种应用都架设在Web平台上,Web业务的迅速发展也引起黑客们的强烈关注,接踵 ...

  2. 2019/12/22 TZOJ

    4986 Team Formation http://www.tzcoder.cn/acmhome/problemdetail.do?&method=showdetail&id=498 ...

  3. 关于在eclipse中配置tomcat的各种坑

    先说在windows下的,java环境什么的就不再记录了,记住装java ee之前,先要装好java se这样java ee才能顺利安装. 主要是安装好tomcat之后,在eclipse中进行配置的时 ...

  4. .net Datatable

    1. ROW remove vs delete datatable dt = new datatable() //fill 5 records for each row as datarow in d ...

  5. 2019 年「计算机科学与工程学院」新生赛 暨ACM集训队选拔赛 # 1

    T1 请问这还是纸牌游戏吗 https://scut.online/p/567 这道题正解据说是方根 这里先放着等以后填坑吧qwq 但是由于这道题数据是随机的 所以其实是有各种水法的(但是我比赛根本没 ...

  6. 读取交货单拣配数量PIKMG(转)

    原文链接:https://www.591sap.com/thread-953-1-1.html SAP交货单交货数量在lips中直接读取,但是拣配数量lfimg,只存在vbfa中,且如果基本计量单位和 ...

  7. swagger2文档使用

    ①.导入依赖 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-sw ...

  8. BZOJ 4821 (luogu 3707)(全网最简洁的代码实现之一)

    题面 传送门 分析 计算的部分其他博客已经写的很清楚了,本博客主要提供一个简洁的实现方法 尤其是pushdown函数写得很简洁 代码 #include<iostream> #include ...

  9. 解决Linux下编译.sh文件报错 “[: XXXX: unexpected operator”

    本人经常在Linux通过编译 .sh文件来生成工程,之前一直都没问题,代码一直都没变,但是今天编译的时候,却提示错误:

  10. opencv2——直方图5

    (一)图像直方图 图像的构成是有像素点构成的,每个像素点的值代表着该点的颜色(灰度图或者彩色图).所谓直方图就是对图像的中的这些像素点的值进行统计,得到一个统一的整体的灰度概念.直方图的好处就在于可以 ...