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))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
posted @ 2017-02-21 14:02  niie9  阅读(185)  评论(0编辑  收藏  举报