高阶函数
定义:把函数作为参数传入,这样的函数称为高阶函数
案例:
def add(a, b, f):
return f(a) + f(b)
print(add(-5, 6, abs)) # 11
常见的高阶函数
map()函数
map内置函数map,map()函数接收两个参数,一个是函数,一个是Iterable(可多个)
map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回
案例
# 求取列表中每个元素的平方值
lst = [1, 2, 3, 4, 5]
lst2 = [3, 5, 7]
def func(item):
return item * item
result = map(func, lst)
print(result)
# <map object at 0x000001C054ED9188>
print(list(result))
# [1, 4, 9, 16, 25]
使用map函数后得到的是一个map类型的对象,是一个迭代器,可以转换为列表输出
使用匿名函数
lst = [1, 2, 3, 4, 5]
lst2 = [3, 5, 7]
result1 = map(lambda x:x * x, lst)
print(list(result1))
print(list(map(lambda x,y:x+y, lst, lst2)))
# [4, 7, 10]
map函数中第一个传入的是函数,第二个值是可迭代对象,传入的函数中传入多少个变量后面就要传入多少个可迭代对象
练习
有列表[1,2,3,4,5],将所有元素转换成str:[‘1’,‘2’,‘3’,‘4’,‘5’]
lst1 = [1,2,3,4,5]
print(list(map(lambda x:str(x), lst1)))
# ['1', '2', '3', '4', '5']
有列表字符串’span’,将各字符转换成对应的ascii码的列表[115, 112, 97, 109]
# lst2 = ['s', 'p', 'a', 'n']
str2 = 'span'
# print(list(map(lambda x:ord(x), str2)))
print(list(map(ord, str2)))
# [115, 112, 97, 110]
有列表[-1,-2,0,1,2],将各元素转换成绝对值[1, 2, 0, 1, 2]
lst3 = [-1,-2,0,1,2]
# print(list(map(lambda x:abs(x), lst3)))
print(list(map(abs, lst3)))
# [1, 2, 0, 1, 2]
将列表中的数保留两位小数
将列表中的数转换为百分数并保留两位小数
a = [0.346574, 2.34534, 6.34523, 8.234534]
print(list(map(lambda x:round(x, 2), a)))
# [0.35, 2.35, 6.35, 8.23]
print(list(map(lambda i:f'{round(i * 100, 2)}%', a)))
# ['34.66%', '234.53%', '634.52%', '823.45%']
filter()函数
Python内建的filter()函数用于过滤序列。和map()类似,filter()也接收一个函数和一个序列
filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。如果得到的结果为真则保留
案例
取出10以内的奇数
# x % 2 可以整除时得到的结果为0,说明为假,不能整除时为真
result = filter(lambda x: x % 2, range(10))
print(list(result))
# [1, 3, 5, 7, 9]
1-200以内开平方是整数的数
import math
result = filter(lambda x: math.sqrt(x) in range(1, 201), range(1,201))
print(list(result))
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196]
过滤出100-999以内的水仙花数
水仙花数:153 = 1的立方 + 5 的立方 + 3的立方
def flower(num):
length = len(str(num))
sum = 0
for i in range(length):
sum += ( num // ( 10 ** i ) % 10 ) ** 3
# print(sum)
if sum == num:
return True
else:
return False
flower_num = filter(flower, range(100, 1000))
print(list(flower_num))
# [153, 370, 371, 407]
把一个序列中的空字符串删掉,[‘A’, ‘’, ‘B’, None, ‘C’, ’ ', ‘a’, 1, 0]
lst = ['A', '', 'B', None, 'C', ' ', 'a', 1, 0]
print(list(filter(lambda x: x and str(x).strip(),lst)))
# ['A', 'B', 'C', 'a', 1]
sorted()函数
sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序
key指定的函数将作用于list的每一个元素上,并根据key函数返回的结果进行排序。
案例
lst = [-6, 3, 2, -9, 7]
# lst.sort() # 会改变原来的列表
# print(lst) # [-9, -6, 2, 3, 7]
print(sorted(lst)) # sorted不会改变原来的列表
# 根据绝对值排序
result = sorted(lst, key=abs)
print(result)
# [2, 3, -6, 7, -9]
bool类型的数据也可以进行排序,True就相当于1,False就相当于0
lst2 = [True, len(lst)>2, 0, 2]
print(sorted(lst2))
# [0, True, True, 2]
sorted只能对同类型的数据进行排序
lst3 = [1, 5, 'a', 7]
print(sorted(lst3))
# TypeError: '<' not supported between instances of 'str' and 'int'
列表里包元组的形式排序
先按照第一个值进行排序,第一个值都一样就按照第二个值进行排序,依次类推
lst = [(True, True, False),
(2, 1, 3), (2, 2, 4),
(False, True, 2),
(False, False, 3)]
print(sorted(lst))
# [(False, False, 3), (False, True, 2), (True, True, False), (2, 1, 3), (2, 2, 4)]
练习
把一个序列中的字符串,忽略大小写排序
lst = ['bob', 'about', 'Zoo', 'Credit']
print(sorted(lst, key=lambda x:x.lower()))
print(sorted(lst, key=str.lower)) # str.lower本身就是一个函数
# ['about', 'bob', 'Credit', 'Zoo']
根据字典中的value值排序
d1 = {"a":3, "b":2, "c":4, "d":1}
print(sorted(d1, key=lambda x:d1[x]))
# ['d', 'b', 'a', 'c']
print(sorted(d1.items(), key=lambda x:x[1]))
# [('d', 1), ('b', 2), ('a', 3), ('c', 4)]
print(dict(sorted(d1.items(), key=lambda x:x[1])))
# {'d': 1, 'b': 2, 'a': 3, 'c': 4}
用python实现这条命令的效果:cat access.log |grep alibaba |sort|uniq -c|sort -nr |head -10
access.log adffa aafdlffaj 234k64l63h lakdfh alibaba 78902313 l;jkafdahiew afdl;kjo2321 lasjfsahi alibaba l;afdf ;jskafdhoieaw alibaba ljsafs asfdasaaga asfdjiwp7892131 lakdfh alibaba 78902313 lakdfh alibaba 78902313 lakdfh alibaba 78902313 ;jskafdhoieaw alibaba ljsafs
# with open('access.log') as fp:
# lst = fp.readlines()
#
# # 过滤出含有alibaba的行
# result = list(filter(lambda line:'alibaba' in line, lst))
# print(result)
# result_num = dict()
# # 统计每一行出现的次数
# for line in list(result):
# result_num[line] = result_num.get(line, 0) + 1
# # print(result_num)
# print(result_num)
# 按行数升序排序
# 循环取出前3个
# result_sort = dict(sorted(result_num.items(), key=lambda x:x[1]))
# # 取前3个
# count = 1
# for i in result_sort:
# print(i)
# count += 1
# if count > 3:
# break
result_num = {}
with open('access.log') as fp:
for line in fp:
# 过滤出含有alibaba的行
if 'alibaba' in line:
result_num[line] = result_num.get(line, 0) + 1
# 切片取出前3个
result_sort = sorted(result_num, key=lambda x:result_num[x])
print(result_sort[:3])
课后练习
lst = [‘a’, ‘1’, ‘bb’, ‘234’, ‘’, ‘9’]
使用reduce 取出lst里的数字 并且转换成整型 —》12349
from functools import reduce
lst = ['a', '1', 'bb', '234', '', '9']
def func(x,y):
return x + y
print(int(reduce(func, list(filter(str.isdigit, lst)))))
# 12349
# 有以下列表:list1=[7, -8, 5, 4, 0, -2, -5]
# 正数在前负数在后
# 正数从小到大
# 负数从大到小
list1=[7, -8, 5, 4, 0, -2, -5]
def func(lst):
# 将列表中的正数选出并按从小到大排序
pos_num = sorted(list(filter(lambda x: x > 0, lst)))
# 将列表中的负数选出按从大到小排序
reg_num = sorted(list(filter(lambda x: x < 0, lst)), reverse=True)
if 0 in lst:
pos_num.append(0)
pos_num.extend(reg_num)
return pos_num
else:
pos_num.extend(reg_num)
return pos_num
print(func(list1))
# [4, 5, 7, 0, -2, -5, -8]
# 这是一个字符串排序,排序规则:小写<大写<奇数<偶数
# s = 'asdf234GDSdsf23'
# 排序:小写-大写-奇数-偶数
# 原理:先比较元组的第一个值,FALSE
s = 'asdf234GDSdsf23'
def new_sort(str):
"""
判断每一个字符是大小写还是奇偶数,根据排序规则可以给不同类型的字符返回一个元组
因为字符排在前面,数字排后面,所以如果是字符就给元组的第一个值赋为False,数字就给True
小写字母在前,大写字母在后,所以如果字符是小写,元组中的第二值就为False,大写就为True
奇数在前偶数在后,如果是奇数,元组中的第二值就为False,偶数就为True
:param str:
:return:
"""
# 判断是字符是字母还是数字
if str.isdigit():
# 判断是否为偶数
if int(str) % 2 == 0:
return (True, True, str)
else:
return (True, False, str)
else:
# 判断是否为大写
if str.isupper():
return (False, True, str)
else:
return (False, False, str)
print(''.join(sorted(s, key=new_sort)))
# addffssDGS33224