python - 函数式编程1
1. map
(1) 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]
(2) map() 作为高阶函数, 事实上它把运算规则抽象了, 因此, 我们不但可以计算简单的f(x)=x^2, 还可以计算任意复杂的函数, 比如, 把这个list所有数字转为字符串:
>>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])) ['1', '2', '3', '4', '5', '6', '7', '8', '9']
只需要一条代码
2. reduce
(1) 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
(2) reduce配合map, 把str转换为int
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))
假设, python没有提供 int() 函数, 我们完全可以自己写一个把字符串转化为证书的函数, 而且只需要几行代码.
(3) 练习
利用map() 函数, 把用户输入的不规范的英文名字, 变为首字母大写, 其他小写的规范名字
输入 ['adam', 'LISA', 'barT'] , 输出 ['Adam', 'Lisa', 'Bart']
def normalize(name): return name[:1].upper() + name[1:].lower() L1 = ['adam', 'LISA', 'baarT'] L2 = list(map(normalize, L1)) print(L2)
(4) 练习
python提供的sum() 函数可以接受一个list并求和, 请编写一个prod()函数, 可以接受一个list并利用reduce()求积:
from functools import reduce def prod(L): def func(x, y): return x * y return reduce(func, L) L = [3, 5, 7, 9] print(prod(L))
(5) 练习
利用map和reduce编写一个str2float函数, 把字符串'123.456'转换成浮点数123.456
from functools import reduce def str2float(s): def str2num(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)) a,b=s.split('.') return str2num(a)+0.1**len(b)*str2num(b) print(str2float('123.456'))
3. filter
(1) filter() 的作用是从一个序列中筛选出符合条件的元素, 过滤序列
(2) 和map() 类似, filter()也接收一个函数和一个序列, 和map()不同的是, filter()把传入的函数依次作用于每个元素, 然后根据返回值是true还是false决定保留还是丢弃该元素.
(3) 例如, 在一个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]
(4) 例如, 把一个序列中的空字符串删掉, 可以这么写:
def not_empty(s): return s and s.strip() list(filter(not_empty, ['A', '', 'B', None, 'C', ' '])) # 结果: ['A', 'B', 'C']
(5) 用filter() 这个高阶函数, 关键在于正确实现一个筛选函数.
(6) filter() 函数返回的是一个Iterator, 也就是一个惰性序列, 所以要强迫filter() 完成计算结果, 需要用list()函数获得所有结果并返回list.
(7) 例子:
用filter() 求素数, 计算素数的一个方法是艾氏筛法
#生成器, 生成从3开始的奇数序列 def _old_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 = _old_iter() while True: n = next(it) yield n it = filter(_not_divisible(n), it) #循环打印 for n in primes(): if n < 200: print(n) else: break
(8) 练习:
回数是指从左向右读和从右向左读都是一样的数, 例如12321, 909. 请利用filter()滤掉非回数:
def is_palindrome(num): n=str(num) if(n==n[::-1]): return num output = filter(is_palindrome, range(1, 100000)) print(list(output))