高阶函数
高阶函数
函数名也是变量
由于abs
函数实际上是定义在import builtins
模块中的,所以要让修改abs
变量的指向在其它模块也生效,要用import builtins; builtins.abs = 10
。
高级函数
# -*- coding: utf-8 -*-
def add(x, y, f):
return f(x) + f(y)
print(add(-5,6,abs))
map/reduce
map
map()
接收两个参数,一个是函数,一个是Iterator
,map()
将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator
返回。
def f(x):
return x * x
r = map(f,[1,2,3,4,5,6,7,8,9])
print(list(r))
把一个list所有数字转化为字符串:print(list(map(str,1,2,3,4)))
reduce
reduce(f,[x1,x2,x3,x4]) = f(f(f(f(x1,x2),x2),x3),x4)
比如序列求和:
from functools import reduce
def add(x,y)
return x + y
print(reduce(add,[1,2,3,4]))
把序列变成整数,结果将是1234:
from functools import reduce
def fn(x,y):
return x * 10 + y
print(reduce(fn,[1,2,3,4]))
把str
转换为int
的函数:
from functools import reduce
def fn(x,y):
return x * 10 + y
def char2num(s):
digits = {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}
return digits[s]
reduce(fn,map(char2num,'1359'))
整理成一个函数:
from functools import reduce
DIGITS = {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}
def str2int(s):
def fn(x,y):
return x * 10 + y
def char2num(s):
return DIGITS[s]
return reduce(fn,map(char2num,s))
print(str2int('12345'))
使用lambda函数进一步简化:
from functools import reduce
DIGITS = {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}
def char2num(s):
return DIGITS[s]
def str2int(s):
return reduce(lambda x, y: x * 10 + y, map(char2num, s)) # 注意计算顺序
print(str2int('12345'))
quiz
- 利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:
['adam', 'LISA', 'barT']
,输出:['Adam', 'Lisa', 'Bart']
:
# -*- coding: utf-8 -*-
L1 = ['adam','LISA','barT']
def normalize(name):
return name[:1].upper() + name[1:].lower()
L2 = list(map(normalize,L1))
print(L2)
- Python提供的
sum()
函数可以接受一个list并求和,请编写一个prod()
函数,可以接受一个list并利用reduce()
求积:
# -*- coding: utf-8 -*-
from functools import reduce
def prod(li):
return reduce(lambda x,y:x * y,li)
print(prod([1,2,3,4])
- 利用
map
和reduce
编写一个str2float
函数,把字符串'123.456'
转换成浮点数123.456
:
# -*- coding: utf-8 -*-
from functools import reduce
DIGITS = {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}
def str2num(li):
return DIGITS[li]
def str2float(li):
n = 0
while li[n] != '.':
n += 1
dec = len(li) - n -1
return float(reduce(lambda x,y:x * 10 + y, map(str2num,li[:-dec-1]+li[-dec:]))/(10 ** dec))
l3 = '123.456'
print(str2float(l3))
filter
filter()
把传入的函数依次作用于每个元素,然后根据返回值是True
还是False
决定保留还是丢弃该元素。
把一个序列中的空格字符串删掉
# and用法与:从左到右扫描,返回第一个为假的表达式值,无假值则返回最后一个表达式值。
# or用法或:从左到右扫描,返回第一个为真的表达式值,无真值则返回最后一个表达式值。
def not_empty(s):
return s and s.strip()
print(list(filter(not_empty, ['A', '', 'B', None, 'C', ' '])))
# 结果: ['A', 'B', 'C']
用filter求素数
矮氏筛法求素数:
# 产生1000内的素数
# 构造一个从3开始的奇数序列生成器
def _odd_iter():
n = 1
while True:
n += 2
yield n
# 定义一个筛选函数
def _not_divisible(n):
return lambda x: x % n > 0 # 匿名函数:定义x,如果x不能被n整除,则返回True
# 定义不断返回下一个素数的生成器
def primes():
yield 2
it = _odd_iter() # 初始序列
while True:
n = next(it) # it本身也是一个generator
yield n
it = filter(_not_divisible(n),it) #通过函数将n整除的去掉
for n in primes():
if n < 1000: # 通过输出值与1000判断
print(n)
else:
break
产生10000以内的回文数
from functools import reduce
def is_palindrome(num):
return str(num) == reduce(lambda x,y:y + x,list(str(num))) # str直接转list
def geplinum(max):
return list(filter(is_palindrome, list(range(max+1)))) #在python中,filter, map, zip等返回可迭代的对象,返回的仅仅是一个元素,并不是一个列表,所以结果前需要使用list
print(geplinum(10000))
取str的倒序字符串也可以更简单地用str(n)[::-1]
来表示。
sorted
sorted()
函数可以对list进行排序,也是一个高阶函数,可以接受一个key
函数来实现自定义排序,返回原值。
>>> sorted([36,5,-12,9,-21],key = abs)
[5, 9, -12, -21, 36]
sorted
对字符串比较时,是通过首字符的ASCII码进行比较,也可以加入反向排序:
>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key = str.lower, reverse = True)
['Zoo', 'Credit', 'bob', 'about']
用sorted对一组tuple按照名字和成绩排序:
# -*- coding: utf-8 -*-
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def by_name(t):
return t[0].lower()
def by_score(t):
return -t[1]
L2 = sorted(L, key = by_name)
L3 = sorted(L, key = by_score)
print(L2)
print(L3)