python高阶函数实例_Python干货-函数式编程之高阶函数

认识高阶函数

函数与变量

print(abs(-1))

1

上例中,abs() 是 python 内置函数,用来求一个数值的绝对值

就以这个函数为例,abs() 是个函数,那 abs 是这个函数的名字,() 才定义其是一个方法,如果只输入 abs,会发生什么情况?

abs

从输出上来看,abs 是一个方法

也就是说,abs 是一个方法的名,它指向了该方法的内存地址

既然这个方法有地址,同样可以将它的地址赋给一个变量

_func = abs

print(_func(-1))

1

也就是说,_func 也指出了 abs 所指向的方法地址,在其后面加上括号后,便可调用所指向的方法

所以,函数名也是变量

函数可以被当作参数传入函数

那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数

定义一个简单的高阶函数:

# 定义一个高阶函数,接收两个方法作为参数

def get_name(f_name, l_name):

# 打印全名

print(f_name, l_name)

# 定义f_name()函数,返回frist name

def first_name(name):

return name

# 定义l_name()函数,返回last name

def last_name(name):

return name

# 将first_name()与last_name当作参数传入get_name()函数中

get_name(first_name('Jack'), last_name('Chen'))

Jack Chen

上例中,get_name()就是一个高阶函数

认识其它高阶函数

map()函数

map()是python的内置函数,它的语法如下:

map(func, *iterables) --> map object

第一个参数是一个方法,第二个参数是一个列表(序列);map的作用是将序列iterables中的元素依次作用到函数func上,并返回一个新的序列对象

示例:

# 定义一个函数,返回一个数的平方

def func_square(num):

return num**2

# 调用map()函数

num_list = map(func_square, [1, 2, 3, 4, 5, 6, 7, 8, 9])

print(list(num_list))

[1, 4, 9, 16, 25, 36, 49, 64, 81]

从结果上来看,序列参数中的每个元素都被作用到func_square函数中,得到一个平方值,最终返回所有数的平方

示例:

print(list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])))

['1', '2', '3', '4', '5', '6', '7', '8', '9']

该例中的序列参数被str()方法都转换成了字符串格式,这也是另一种运用

reduce()函数

reduce()函数将一个函数作用在一个序列上,这个函数必须接收两个参数,reduce()函数会继续和序列的下一个元素做累积运算

示例:

# 从functolls模块中导入reduce函数

from functools import reduce

# 定义一个加法函数

def add(x, y):

return x+y

# 调用reduce()函数

result = reduce(add, [1, 2, 3, 4, 5])

print(result)

15

序列[1, 2, 3, 4, 5]的每一个元素作用到add()方法上,将该函数得到的结果再与下一个元素传入add()方法中,直到结束,得到的结果就是1+2+3+4+5=15

示例:如何将序列[1, 2, 3, 4, 5]转换成数字12345

# 从functolls模块中导入reduce函数

from functools import reduce

# 定义一个转换函数

def fn(x, y):

return x * 10 + y

# 调用reduce()函数

result = reduce(fn, [1, 2, 3, 4, 5])

print(result)

12345

这里定义了一个函数fn(),该函数可以将传入的丙个参数做十位数与个位数的运算,再将得出的结果与下一个元素做同样的处理,原来的十位数再乘10变成了百位数,个位数则成了十位数,新的y元素则成了个位数,依此类推,最后得出了结果12345

map() 函数与 reduce() 函数的结合

示例:将字符串转换成列表,再将该列表做累加运算

# 从functolls模块中导入reduce函数

from functools import reduce

# 定义一个转换函数

def fn(x, y):

return x * 10 + y

# 定义一个数字转换字符的方法

def char_num(x):

return int(x)

# 调用reduce()函数

result = reduce(fn, map(char_num, '12345'))

print(result)

12345

map() 函数会将字符串 '12345'当作一个字符序列今次作用到 char_num() 方法上,最终会返回一个数字列表,这个列表又会依次作用到 fn() 函数上,得到的结果与上一个例子结果是一致的

python提供了更加强大的函数编程,可以将多个方法封装到一个方法里,上面的例子中的两个方法就可以包装成一个方法,使用的时候也只需要调用一次即可同,如下:

# 从functolls模块中导入reduce函数

from functools import reduce

# 顶层包装函数

def func_all():

# 定义一个转换函数

def fn(x, y):

return x * 10 + y

# 定义一个数字转换字符的方法

def char_num(x):

return int(x)

# 调用reduce()函数

return reduce(fn, map(char_num, '12345'))

print(func_all())

12345

也可以使用lambda函数进行简化,如下:

# 从functolls模块中导入reduce函数

from functools import reduce

# 定义一个数字转换字符的方法

def char_num(x):

return int(x)

# 调用reduce()函数

result = reduce(lambda x, y : x * 10 +y, map(char_num, '12345'))

print(result)

12345

filter() 函数

filter() 函数接收一个函数和一个序列作为参数,并将序列中的每一个元素都作用到传入函数上,根据该函数返回的布尔值,来决定当前元素是否保留

示例:筛选一个序列,保留奇数

# 奇数筛选函数

def is_odd(x):

return x % 2 == 1

# 调用filter()函数

result = filter(is_odd, [1, 2, 3, 4, 5])

print(list(result))

[1, 3, 5]

示例:删除掉序列中的空字符串

# 筛选空字符串

def empty_str(x):

return x.strip() != ''

# 调用filter()函数

result = filter(empty_str, ['', '2', 'a', ' '])

print(list(result))

['2', 'a']

注意:filter()函数返回的是一个Iterator,也就是一个惰性序列,所以要强迫filter()完成计算结果,需要用list()函数获得所有结果并返回list

示例:筛选质数

质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。

因数,或称为约数,数学名词。定义:整数a除以整数b(b≠0) 的商正好是整数而没有余数,我们就说b是a的因数。0不是0的因数。

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

首先,列出从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开始的奇数序列

def _odd_iter():

n = 1

while True:

n = n + 2

yield n # yield返回的是一个生成器,所包含的序列将是无限的

# 定义一个筛选函数,

def _not_divisible(n):

return lambda x: x % n > 0 # 这里将lambda匿名函数返回

# 定义一个生成器函数

def primes():

yield 2 # 事先在生成器里返回了2

it = _odd_iter() # 初始序列,这里都是奇数,返回的是一个生成器

while True:

n = next(it) # 返回序列的第一个数,之后返回下一个

yield n

it = filter(_not_divisible(n), it) # 构造新序列,每次将所有奇数作用于筛选函数返回的函数上

# 打印100以内的素数:

l = []

for n in primes():

if n < 100:

l.append(n)

else:

break

print(l)

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

yield 是一个类似 return 的关键字,只是这个函数返回的是个生成器

当你调用这个函数的时候,函数内部的代码并不立马执行 ,这个函数只是返回一个生成器对象

当你使用for进行迭代的时候,函数中的代码才会执行

sorted() 函数

sorted() 函数是 python 中内置的函数,可以对 list 进行排序

示例:

l = sorted([1, 4, 5, 2, 3])

print(l)

[1, 2, 3, 4, 5]

此外,sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序

示例:按绝对值大小排序

# 按大小排序

l = sorted([1, -5, 3, -2, -4])

print(l)

# 按绝对值排序

l = sorted([1, -5, 3, -2, -4], key=abs)

print(l)

[-5, -4, -2, 1, 3]

[1, -2, 3, -4, -5]

key指定的函数将作用于list的每一个元素上,并根据key函数返回的结果进行排序

sorted() 也可以对字符串进行排序,示例:

l_str = sorted(['hello', 'my', 'name', 'is', 'Jack'])

print(l_str)

['Jack', 'hello', 'is', 'my', 'name']

默认情况下,对字符串排序,是按照ASCII的大小比较的,由于'J' < 'a',结果,大写字母J会排在小写字母h的前面

如果纯粹的想按字母进行排序,而不分大小写,则可以将所有的字母都转换成小写,再来进行排序,示例如下:

l_str = sorted(['hello', 'my', 'name', 'is', 'Jack'], key=str.lower)

print(l_str)

['hello', 'is', 'Jack', 'my', 'name']

还可以反向排序,需要第三个参数reverse=True,示例如下:

l_str = sorted(['hello', 'my', 'name', 'is', 'Jack'], key=str.lower, reverse=True)

print(l_str)

['name', 'my', 'Jack', 'is', 'hello']

你可能感兴趣的:(python高阶函数实例)