Python之函数式编程——高阶函数

高阶函数

函数本身也可以赋值给变量,即:变量可以指向函数

函数名也是变量

函数接收另一个函数作为参数,这种函数成为高阶函数,函数式编程就是指这种高度抽象的编程范式

1>map/reduce

link:  https://ai.google/research/pubs/pub62

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

>>> def f(x):
 return x*x

>>> r= map(f, [1,2,3,4,5,6,7])
>>> list(r)
[1, 4, 9, 16, 25, 36, 49]
>>>

把所有数字转化为字符串:

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

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

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

对一个序列求和:

>>> from functools import reduce
>>> def add(x, y):
...     return x + y
...
>>> reduce(add, [1, 3, 5, 7, 9])
25

Pratice:利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:['adam', 'LISA', 'barT'],输出:['Adam', 'Lisa', 'Bart']

>>> def normalize(name):
 return name.capitalize()

>>> L1=['adam','LISA','bhhgI']
>>> list(map(normalize,L1))
['Adam', 'Lisa', 'Bhhgi']
>>>

Practice: Python提供的sum()函数可以接受一个list并求和,请编写一个prod()函数,可以接受一个list并利用reduce()求积:

>>> from functools import reduce
>>> def prod(L):
 def fn(x,y):
  return x*y
 return reduce(fn,L)

>>> prod([3,5,7,9])
945
>>>

2>filter:

map()类似, filter()也接收一个函数和一个序列。和 map()不同的是, filter()把传入的函数依次作用于每个元素,然后根据返回值是 True还是 False决定保留还是丢弃该元素。
在一个list中,删掉偶数,只保留奇数,可以这么写:
>>> def is_odd(n):
 return n%2==1
>>> list(filter(is_odd, [1,2,3,4,5,6,7,0]))
[1, 3, 5, 7]
>>>
用filter求素数:

计算素数的一个方法是埃氏筛法,它的算法理解起来非常简单:

首先,列出从2开始的所有自然数,构造一个序列:

2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...

取序列的第一个数2,它一定是素数,然后用2把序列的2的倍数筛掉:

3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...

取新序列的第一个数3,它一定是素数,然后用3把序列的3的倍数筛掉:

5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...

取新序列的第一个数5,然后用5把序列的5的倍数筛掉:

7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...

不断筛下去,就可以得到所有的素数。

用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)
  //设置退出循环条件
>>> for n in primes():
 if n<1000:
  print(n)
 else:
  break

Practice: 回数是指从左向右读和从右向左读都是一样的数,例如12321909。请利用filter()筛选出回数
>>> def is_palindrome(n):
 if str(n)==str(n)[::-1]:
  return n
 
>>> list(filter(is_palindrome, range(1,200)))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191]
>>> list(filter(is_palindrome, range(1,1000)))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191, 202, 212, 222, 232, 242, 252, 262, 272, 282, 292, 303, 313, 323, 333, 343, 353, 363, 373, 383, 393, 404, 414, 424, 434, 444, 454, 464, 474, 484, 494, 505, 515, 525, 535, 545, 555, 565, 575, 585, 595, 606, 616, 626, 636, 646, 656, 666, 676, 686, 696, 707, 717, 727, 737, 747, 757, 767, 777, 787, 797, 808, 818, 828, 838, 848, 858, 868, 878, 888, 898, 909, 919, 929, 939, 949, 959, 969, 979, 989, 999]
>>>

3>sorted:

Python内置的sorted()函数就可以对list进行排序

>>> sorted([34,7,-9,0,345])
[-9, 0, 7, 34, 345]

此外,sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序,例如按绝对值大小排序:

>>> sorted([67,89,-95,-9,0,2,-1], key=abs)
[0, -1, 2, -9, 67, 89, -95]
实现字符串的反向排序并忽略大小写:

>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
['Zoo', 'Credit', 'bob', 'about']

Practice: 

假设我们用一组tuple表示学生名字和成绩:

L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]

请用sorted()对上述列表分别按名字和分数排序:

>>> L=[('Bob',75),('Adam',92),('Bart',66),('Lisa',88)]
>>> def by_name(t):
 return t[0]

>>> def by_score(t):
 return t[1]

>>> sorted(L, key=by_name)
[('Adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88)]
>>> sorted(L, key=by_score)
[('Bart', 66), ('Bob', 75), ('Lisa', 88), ('Adam', 92)]
>>>





猜你喜欢

转载自blog.csdn.net/johnny_timmy/article/details/80507194