高阶函数
函数可以接收另一个函数作为参数,称之为高阶函数。函数式编程就是指这种高度抽象的编程范式。
例如:
1
2
3
4
|
def add(x, y, f):
return f(x) + f(y)
add(-5, 6, abs) # 结果为11
|
Python内置高阶函数
map(function, iterable, …)
map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。返回的是一个Iterator。
例如:
1
2
3
4
5
6
7
8
|
from collections import Iterator
def f(x):
return x * x
r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
print(type(r)) # 打印r的类型
print(isinstance(r,Iterator)) # 验证r是否是Iterator。结果True
print(r)
print(list(r))
|
执行以上程序会输出如下结果:
1
2
3
4
|
<class 'map'>
True
<map object at 0x7ffb2e1f0898>
[1, 4, 9, 16, 25, 36, 49, 64, 81]
|
例如,数字转为字符串
1
2
3
4
5
|
l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
m = map(str, l)
print(type(m))
print(m)
print(list(m))
|
执行以上程序会输出如下结果:
1
2
3
|
<class 'map'>
<map object at 0x7fb35d184828>
['1', '2', '3', '4', '5', '6', '7', '8', '9']
|
filter(function, iterable)
filter()函数用于过滤序列。接收一个函数和一个序列。filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
filter()函数返回的是一个Iterator,也就是一个惰性序列,所以要强迫filter()完成计算结果,需要用list()函数获得所有结果并返回list。
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
from collections import Iterator
def f1(x):
if x>20:
return True
else:
return False
l1 = [ 1, 2, 3, 42, 67, 16 ]
f = filter(f1, l1)
print(type(f)) # 打印f的类型
print(isinstance(f,Iterator)) # 验证f是否是Iterator。结果True
print(f)
print(list(f))
|
执行以上程序会输出如下结果:
1
2
3
4
|
<class 'filter'>
True
<filter object at 0x7f60222568d0>
[42, 67]
|
当然,也可以使用Iterator的next方法来迭代。
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
from collections import Iterator
def f1(x):
if x>20:
return True
else:
return False
l1 = [ 1, 2, 3, 42, 67, 16 ]
f = filter(f1, l1)
print(f.__next__) # 打印迭代器对象f的next对象
print(f.__next__()) # 获取第一个成员值
print(f.__next__()) # 获取第二个成员值
print(f.__next__()) # 迭代结束
|
执行以上程序会输出如下结果:
1
2
3
4
5
6
7
|
<method-wrapper '__next__' of filter object at 0x7f349089c8d0>
42
67
Traceback (most recent call last):
File "main.py", line 15, in <module>
print(f.__next__())
StopIteration
|
sorted(iterable, *, key=None, reverse=False)
sorted()用于对集合进行排序(这里说的集合是对可迭代对象的一个统称,他们可以是列表、字典、set、甚至是字符串,字节)。返回一个新排列好的集合。
1.默认排序
默认情况,sorted函数将按列表升序进行排序,并返回一个新列表对象,原列表保持不变,最简单的排序
例如:
1
2
3
4
5
6
7
|
nums = [3,4,5,2,1]
new_nums = sorted(nums)
print(type(nums))
print(type(new_nums))
print(nums is new_nums)
print(nums)
print(new_nums)
|
执行以上程序会输出如下结果:
1
2
3
4
5
|
<class 'list'>
<class 'list'>
False
[3, 4, 5, 2, 1]
[1, 2, 3, 4, 5]
|
2.降序排序
如果要按照降序排列,只需指定参数 reverse=True 即可
例如:
1
2
3
4
5
6
7
|
nums = [3,4,5,2,1]
new_nums = sorted(nums,reverse=True)
print(type(nums))
print(type(new_nums))
print(nums is new_nums)
print(nums)
print(new_nums)
|
执行以上程序会输出如下结果:
1
2
3
4
5
|
<class 'list'>
<class 'list'>
False
[3, 4, 5, 2, 1]
[5, 4, 3, 2, 1]
|
3.自定义规则排序
如果要按照某个特定的规则排序,则需指定参数key, key是一个函数(或其它可调用对象),例如:一个字符串构成的列表,我想按照字符串的长度来排序。len是内建函数,sorted函数在排序的时候会用len去获取每个字符串的长度来排序。
例如:
1
2
3
4
5
6
7
|
chars = ['Andrew', 'This', 'a', 'from', 'is', 'string', 'test']
new_chars = sorted(chars, key=len)
print(type(chars))
print(type(new_chars))
print(chars is new_chars)
print(chars)
print(new_chars)
|
执行以上程序会输出如下结果:
1
2
3
4
5
|
<class 'list'>
<class 'list'>
False
['Andrew', 'This', 'a', 'from', 'is', 'string', 'test']
['a', 'is', 'This', 'from', 'test', 'Andrew', 'string']
|
4.复合排序
如果是一个复合列表结构,例如:由元组构成的列表,要按照元组中的第二个元素排序,那么可以用 lambda 定义一个匿名函数,这里就是按照第二个元素的字母升序来排列的
例如:
1
2
3
4
5
6
7
|
stu = [('zhang', 'A'), ('li', 'D'), ('wang', 'C')]
new_stu = sorted(stu, key=lambda x: x[1])
print(type(stu))
print(type(new_stu))
print(stu is new_stu)
print(stu)
print(new_stu) #按照字母 A-C-D 的顺序排列。
|
执行以上程序会输出如下结果:
1
2
3
4
5
|
<class 'list'>
<class 'list'>
False
[('zhang', 'A'), ('li', 'D'), ('wang', 'C')]
[('zhang', 'A'), ('wang', 'C'), ('li', 'D')]
|
5、类的实例对象排序
如果要排序的元素是自定义类,例如Student类按照年龄来排序,则可以写成
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class Student:
def __init__(self, name, grade, age):
self.name = name
self.grade = grade
self.age = age
def __repr__(self):
return repr((self.name, self.grade, self.age))
student_objects = [
Student('john', 'A', 15),
Student('jane', 'B', 12),
Student('lily', 'A', 12),
Student('dave', 'B', 10), ]
print(sorted(student_objects, key=lambda t:t.age))
# 打印 [('dave', 'B', 10), ('jane', 'B', 12), ('lily', 'A', 12), ('john', 'A', 15)]
|
6.多个值排序
和数据库的排序一样,sorted也可以根据多个字段来排序,例如我有先要根据age排序,如果age相同的则根据grade排序,则可以使用元组:
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class Student:
def __init__(self, name, grade, age):
self.name = name
self.grade = grade
self.age = age
def __repr__(self):
return repr((self.name, self.grade, self.age))
student_objects = [
Student('john', 'A', 15),
Student('jane', 'B', 12),
Student('lily', 'A', 12),
Student('dave', 'B', 10), ]
print(sorted(student_objects, key=lambda t:(t.age, t.grade)))
# 打印 [('dave', 'B', 10), ('lily', 'A', 12), ('jane', 'B', 12), ('john', 'A', 15)]
|
7.不可直接比较的值排序
前面碰到的排序场景都是建立在两个元素是可以互相比较的前提下,例如数值按大小比较, 字母按ASCII顺序比较,如果遇到本身是不可比较的,需要我们自己来定义比较规则的情况如何处理呢?
举个简单的例子:
例如:
1
2
3
4
|
nums = [2, 1.5, 2.5, '2', '2.5']
print(sorted(nums))
TypeError: '<' not supported between instances of 'str' and 'int'
|
我们需要使用 functools 模块中的 cmp_to_key 来指定比较函数。
例如:
1
2
3
4
5
6
7
8
9
10
|
import functools
def compare(x1, x2):
if isinstance(x1, str):
x1 = float(x1)
if isinstance(x2, str):
x2 = float(x2)
return x1 - x2
print(sorted(nums, key=functools.cmp_to_key(compare)))
# 打印 [1.5, 2, '2', 2.5, '2.5']
|
8.优化排序
对于集合构成的列表,有一种更高效的方法指定这个key
例如:
1
2
3
4
5
6
|
from operator import itemgetter
students = [('zhang', 'A'), ('li', 'D'), ('wang', 'C')]
print(sorted(students, key=itemgetter(1)))
# 打印 [('zhang', 'A'), ('wang', 'C'), ('li', 'D')]
|
9.高级排序
同样的,对于自定义类,也有一种更高效的方法指定key
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
from operator import attrgetter
class Student:
def __init__(self, name, grade, age):
self.name = name
self.grade = grade
self.age = age
def __repr__(self):
return repr((self.name, self.grade, self.age))
student_objects = [
Student('john', 'A', 15),
Student('jane', 'B', 12),
Student('dave', 'B', 10), ]
print(sorted(student_objects, key=attrgetter('age')))
# 打印 [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
# 如果参与排序的字段有两个怎么办,你可以这样:
print(sorted(student_objects, key=attrgetter('grade', 'age')))
# 打印 [('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
|
reduce
在Python3里,reduce()函数已经被从全局名字空间移除了,它现在被放置在functools模块里。reduce把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
例如:
1
2
3
4
5
6
7
8
|
from functools import reduce
L=[0, 1, 2, 3, 4, 5, 6]
def f4(x,y):
return(x+y)
r = reduce(f4, L) #0+1+2+3+4+5+6
print(type(r)) #打印r的类型
print(r)
|
执行以上程序会输出如下结果:
reduce()还可以接收第3个可选参数,作为计算的初始值。
例如:
1
2
3
4
5
|
from functools import reduce
print(reduce(lambda x,y:x*y,range(1,3),5)) # 相当于(5*1*2)
print(reduce(lambda x,y:x*y,range(1,6),3)) #相当于(3*1*2*3*4*5)
print(reduce(lambda x,y:x+y,[1,2,3,4,5,6])) # 相当于(0+1+2+3+4+5+6)
|
执行以上程序会输出如下结果:
转载请注明本网址。