【摘要】函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数! Python对函数式编程提供部分支持。把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式。
1.map()
map() 会根据提供的函数对指定序列做映射。
第一个参数接受一个函数名,后面的参数接受一个或多个可迭代的序列,返回的是一个集合。
例如:我们要对传入的5个数字进行排序。首先要有一个列表存储这输入的五个数字,而列表对这五个数字是以字符串的格式排序,如果需要排序,首先要依次转换成为int型,再使用sorted方法排序。
nums = [input() for i in range(5)]
print(nums)
# 使用for循环将数值转为整形
int_nums = [int(num) for num in nums]
print(sorted(int_nums))
我们知道map()会根据提供的函数对执行序列做映射,那对这样的需求,我们就可以使用map(int,nums),即对nums这个序列执行int函数来做映射。
nums = [input() for i in range(5)]
print(nums)
# 使用map转换数值为整形
map_num = map(int, nums)
sorted_num = sorted(map_num)
print(sorted_num)
判断我们传入的map_num是否为可迭代对象
from collections.abc import Iterable
print(isinstance(map_num, Iterable))
当seq多于一个时,map可以并行(注意是并行)地对每个seq执行如下图所示的过程:
例如:我们定义一个函数line,接收两个参数,返回这两个参数的二元一次方程。
def line(num1, num2):
return num1 *10 + num2
再生成两个序列
nums1 = range(2, 6)
nums2 = range(1, 6)
# nums1 = 2 3 4 5
# nums2 = 1 2 3 4 5
使用map()函数对这两个序列进行line函数的映射。
result = map(line, nums1, nums2)
print(list(result))
总结:
map的传递,函数名可以是内置函数、匿名函数、自定义函数。
map的传递,可迭代对象可以是多个序列。
2. reduce()
reduce() 函数会对参数序列中元素进行累积。
第一个参数接受一个函数名,后面的参数接受一个或多个可迭代的序列,返回的是一个结果。
【注】py2中reduce是内置的高阶函数, py3需要导入functools模块
例如:对序列中的数值求和
# 求两个数值和的匿名函数定义;
add = lambda x, y: x + y
result = reduce(add, [1, 2, 3, 4])
print(result)
reduce的工作机制: result=add(add(add(1, 2), 3), 4)
再例如求10的阶乘:
result = reduce(lambda x, y:x*y, range(1, 10))
print(result)
3.filter()
filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
第一个参数接受一个函数名,后面的参数接受一个或多个可迭代的序列,返回的是一个序列。
例如:求100以内的所有偶数。当然最简单还是range(0, 101, 2)
如果用filter()函数,我们就需要定义一个判断偶数的函数,将其作为参数传给filter()。
def is_odd(num):
"""
判断是否为偶数, 返回值为Bool类型
:param num:
:return:
"""
return num %2 ==0
将序列和自定义is_odd函数传入
odd_nums = filter(is_odd, range(0,101))
print(list(odd_nums))
截图不完全。
当然也可以直接将is_odd函数写成匿名函数形式作为参数传入
odd_nums = filter(lambda num: num%2==0, range(0, 101))
print(list(odd_nums))
再看几个例子:
1.获取100以内能被3或者5整除的所有数
result1 = filter(lambda num: num % 3 == 0 or num % 5 == 0, range(100))
print(list(result1))
2.获取2000-2999年,所有的闰年
is_leap = lambda year: (year % 4 == 0 and year % 100 !=0) or year % 400 == 0
result2 = filter(is_leap, range(2000, 3000))
print(list(result2))
3.获取1000内容所有的素数
def is_prime(num):
"""判断是否为素数"""
if num < 2:
return False
for i in range(2, num):
if num %i == 0:
return False
else:
return True
result3 = filter(is_prime, range(1001))
print(list(result3))
4.max/min/sorted
goods = [
["苹果", 2, 1000],
["电脑", 9999, 300],
["手机", 5999, 790]
]
top_price = max(goods, key=lambda x: x[1])
print(top_price)
print("价格最高的商品名称: ", top_price[0])
low_count = min(goods, key=lambda x: x[2])
print("库存量最少的商品名称: ", low_count[0])
high_count = max(goods, key=lambda x: x[2])
print("库存量最多的商品名称: ", high_count[0])
sorted() 函数对所有可迭代的对象进行排序操作。返回重新排序的列表。
sorted(iterable, key=None, reverse=False)
key: 主要是用来进行比较的元素,只有一个参数,
reverse: 排序规则,True 降序 ,False 升序(默认)。
例如:携程有个笔试题,要求将所有的偶数移动到前面, 将所有的奇数移动到最后
用sorted(),一行代码就搞定啦。
li =list(range(10))
sorted_li = sorted(li, key=lambda num: 0 if num%2==0 else 1)
print(sorted_li)
【补充】python排序sort()和sorted()的区别是什么?
- 排序对象不同: sort 是应用在list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
- 返回值不同:
list 的 sort 方法返回的是对已经存在的列表进行操作,无返回值,
内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
提出一个问题:
将result再转换成字典后,d为什么为空呢?
因为在python3中,range、map、zip、reduce等生成的都是生成器对象,一边循环一边计算,将执行完了也就没有了(range除外)。而在python2中,生成的是列表,并非生成器对象,很明显python3对此做了优化,节省了内存空间。