高阶函数
函数本身也可以赋值给变量,即:变量可以指向函数
函数名也是变量
函数接收另一个函数作为参数,这种函数成为高阶函数,函数式编程就是指这种高度抽象的编程范式
1>map/reduce
link: https://ai.google/research/pubs/pub62
map()函数接收两个参数,一个是函数,一个是Iterable
,map
将传入的函数依次作用到序列的每个元素,并把结果作为新的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
决定保留还是丢弃该元素。
return n%2==1
>>> list(filter(is_odd, [1,2,3,4,5,6,7,0]))
[1, 3, 5, 7]
>>>
首先,列出从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, ...
不断筛下去,就可以得到所有的素数。
3
开始的奇数序列:
n=1
while True:
n=n+2
yield n
>>> def _not_divisible(n):
return lambda x:x%n>0
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
12321
,909
。请利用filter()
筛选出回数
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)]
>>>