python中的高阶函数

高阶函数

定义:把函数作为参数传入,这样的函数称为高阶函数

案例

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值