day11_实参高阶函数
1.函数匿名
没有函数名的函数
函数名 = lambda 形参列表:返回值
相当于
def 函数名(形参列表):
return 返回值
sum1 = lambda num1,num2:num1+num2
sum1 = lambda num1,num2:num1+num2
print(sum1(1,2))
print(sum1(num1=100,num2=200))
匿名的本质还是函数,之前函数中除了定义函数的语法以外的内容都适用于匿名
用处:简洁,不用用def来定义函数
练习:写一个匿名函数判断指定的年是否是闰年
year = int(input())
is_leapyear = lambda year:True if (year%400 == 0 or (year%4==0 and year%100!=0)) else False
print(is_leapyear(year))
2.函数就是变量
python中定义函数就是定义类型是function的变量,函数名就是变量名
普通变量能做的事情,函数都可以做
返回值是高阶函数:如果一个函数的返回值是函数,那么这个函数就是返回值高阶函数
def func4():
def t2():
print('你好')
return t2
result = func4()()
练习
list3 = []
for x in range(5):
list3.append(lambda i:x*i)
print(list3[0](2))
print(list3[1](2))
print(list3[2][2])
x = 0 :[lambda i:x*i]
x = 1:[lambda i:x*i, lambda i:x*i]
x =2 :[lambda i:x*i lambda i:x*i lambda i:x*i]
x =3:[lambda i:x*i,lambda i:x*i,lambda i:x*i,lambda i:x*i]
x =4 :[lambda i:x*i, lambda i:x*i, lambda i:x*i, lambda i:x*i,lambda i:x*i]
调用函数的时候才会执行,所以x=4的时候才会调用,x=4,4*2=8
3.实参高阶函数的应用
python中常用的实参高阶函数:max、min、sorted、map、reduce
1) max和min
students = [{'name':'小一','age':18,'score':92},
{'name':'小二','age':14,'score':93},
{'name':'小三','age':15,'score':94},
{'name':'小四','age':16,'score':95},
{'name':'小五','age':17,'score':97}
]
max(序列,key=函数) - 按照key对应的函数指定的规则来获取序列中元素的最大值
函数的要求:
a.有且只有一个参数(这个参数指向的是序列中的元素);
b.有一个返回值(比较大小的对象)
# 个位数最大:
nums = [29, 32, 4, 35, 57]
result = max(nums, key=lambda item: item % 10)
print(result)
# nums中最大的数
result = max(nums,key=lambda item:item)
print(result)
# 获取tels中尾号最大的元素
tels = ['17289993', '2828902', '78289191', '1910290']
max_tel = max(tels,key=lambda item:item[-1])
print(max_tel)
2) sorted(序列,key= 序列)
result = sorted(nums,key=lambda item:item%10)
print(result)
# 按学生分数从大到小排序
students = [
{'name': '小明', 'age': 18, 'score': 92},
{'name': '张三', 'age': 24, 'score': 99},
{'name': '李四', 'age': 30, 'score': 87},
{'name': '王五', 'age': 16, 'score': 62}
]
result = sorted(students,key=lambda item:item['score'],reverse=True)
print(result)
3) map(函数,序列)
将序列中的元素按照函数指定的规则转换成一个新的序列
函数的要求:
a. 有且只有一个参数(指向序列中的每个元素)
b.需要一个返回值(返回值就是新序列中的元素)
nums = [18,23,9,67,16]
new_nums = map(lambda item:item%10,nums)
print(list(new_nums))
# map提取所有手机号码后四位
tels = ['15283131024','15283131033','15283131544','15283132012']
new_tels = map(lambda item:item[-4:],tels)
print(list(new_tels))
4) map(函数,序列1,序列2)
函数要求:
a. 有且只有两个参数(分别指向两个序列中的元素)
b.需要一个返回值(返回值就是新序列中的元素)
names = ['张三', '李四', '王五', '小张', '小马', '小花']
scores = [90, 89, 87, 86, 85, 84]
result = list(map(lambda item1,item2:{'name':item1,'scores':item2},names,scores))
print(result)
#练习
list1 = [10, 2, 78, 90, 16]
str1 = 'abcde'
list2 = [(10, 20), (3, 7), (9, 10), (103, 56), (1, 2)]
# ['10a20', '2b7', '78c10', '90d56', '16e2']
result = list(map(lambda x,y,z:f'{x}{y}{z[-1]}',list1,str1,list2))
print(result)
5) reduce(函数,序列,初始值)
将序列中的元素按照函数指定的规则合并成一个数据
函数的要求:
1)有且只有两个参数
第一个参数:第一次指向初始值,从第二次开始指向上一次的计算结果
第二个参数:指向序列中的每个元素
2)描述合并规则
nums = [20,30,40,67]
result = reduce(lambda x,y:x+y,nums,0)
print(result)
# 0 20 ---> 20
# 20 30 ---> 50
# 50 40 ---> 90
# 90 67 ---> 157
# [18,90,89,78,67] 求元素个位数的和
nums = [18,90,89,78,67]
result = reduce(lambda x,y:x+y%10,nums,0)
print(result)
goods = [
{'name': 'XXX泡面', 'price': 3, 'count': 5},
{'name': 'XX口红', 'price': 312, 'count': 2},
{'name': 'xx矿泉水', 'price': 1, 'count': 10}
]
result = reduce(lambda x,y:x+y['price']*y['count'],goods,0)
print(result)
# 练习1 :乘积
nums = [18, 90, 89, 78, 67]
result = reduce(lambda x, y: x * y, nums, 1)
print(result)
# 练习2:个位数乘积
nums = [18, 90, 89, 78, 67]
result = reduce(lambda x, item: x * item % 10, nums, 1)
print(result)
# 练习3 : 提取字符串列表中所有元素的最后一个字符
# ['abc','hello','你好','123']---->['co好3']
list1 = ['abc', 'hello', '你好', '123']
result = reduce(lambda x, item: x + item[-1], list1, '')
print(result)
# 练习4:计算列表中所有数字元素的和
# [18, 'abc', 10.3, True, '你好'] -> 28.3
nums = [18, 'abc', 10.3, True, '你好']
new_nums = [x for x in nums if (type(x)==int or type(x)==float)]
result = reduce(lambda x, y: x + y, new_nums, 0)
print(result)
result_1 = reduce(lambda x, item: x + (item if type(item) in (int, float) else 0), nums, 0)
print(result_1)
作业
- 已经列表points中保存的是每个点的坐标(坐标是用元组表示的,第一个值是x坐标,第二个值是y坐标)
points = [
(10, 20), (0, 100), (20, 30), (-10, 20), (30, -100)
]
以下问题使用实参高阶函数来解决
1)获取列表中y坐标最大的点
y_max= max(points,key=lambda item:item[1])
# 改:绝对值的话,加一句:
result = [x for x in points if x[-1]==y_max[-1]]
2)获取列表中x坐标最小的点
x_min = min(points,key=lambda item:item[0])
#改:
result = [x for x in points if x[0]==x_min[0]]
3)获取列表中距离原点最远的点
dis_far = max(points,key=lambda item:(item[0]**2+item[1]**2)**0.5)
不用再开方,判断是一样的
dis_far = max(points,key=lambda item:(item[0]**2+item[1]**2))
result = [x for x in points if x[0]**2+x[1]**2==dis_far
print(resu)
4)将点按照点到x轴的距离大小从大到小排序
new_points = sorted(points,key=lambda item:item[1])
改
new_points = sorted(points,key=lambda item:abs(item[-1]),reverse=True)
- 求列表 nums 中绝对值最大的元素
nums = [1.2,34,-56,'a']
abs_max = max(nums,key=lambda item:abs(item) if type(item)in(int,float) else 0)
print(abs_max)
- 已经两个列表A和B,用map函数创建一个字典,A中的元素是key,B中的元素是value
A = ['name', 'age', 'sex']
B = ['张三', 18, '女']
新字典: {'name': '张三', 'age': 18, 'sex': '女'}
A = ['name', 'age', 'sex']
B = ['张三', 18, '女']
dict1 =list(map(lambda item1,item2:{item1:item2},A,B))
print(dict1)
改
A = ['name', 'age', 'sex']
B = ['张三', 18, '女']
dict1 =dict(map(lambda item1,item2:(item1,item2),A,B))
print(dict1)
- 已经三个列表分别表示4个学生的姓名、学科和班号,使用map将这个三个列表拼成一个表示每个学生班级信息的的字典
names = ['小明', '小花', '小红', '老王']
nums = ['1906', '1807', '2001', '2004']
subjects = ['python', 'h5', 'java', 'python']
结果:{'小明': 'python1906', '小花': 'h51807', '小红': 'java2001', '老王': 'python2004'}
stu_dict = list(map(lambda item1,item2,item3:{item1:item2+item3},names,subjects,nums))
改
result = dict(map(lambda x,y,z:(x,z+y),names,nums,subjects))
print(result)
- 已经一个列表message, 使用reduce计算列表中所有数字的和(用采用列表推导式和不采用列表推导式两种方法做)
message = ['你好', 20, '30', 5, 6.89, 'hello']
结果:31.89
#不用推导式
sum_message = reduce(lambda i1, i2: i1 + (i2 if type(i2) in (int, float) else 0), message, 0)
# 用列表推导式
new_message = [x for x in message if type(x) in(int,float)]
sum_message = reduce(lambda i1,i2:i1+i2,new_message,0)
改
result = reduce(lambda x,item:x+item,[i for i in message if type(i)in (int,float)],0)
print(result)
-
已知一个字典列表中保存的是每个学生各科的成绩,
1)计算并添加每个学生的平均分
2)按照平均分从高到低排序
studens = [
{'name': 'stu1', 'math': 97, 'English': 67, 'Chinese': 80},
{'name': 'stu2', 'math': 56, 'English': 84, 'Chinese': 74},
{'name': 'stu3', 'math': 92, 'English': 83, 'Chinese': 78},
{'name': 'stu4', 'math': 62, 'English': 90, 'Chinese': 88}
]
# 计算平均分
studens = [
{'name': 'stu1', 'math': 97, 'English': 67, 'Chinese': 80, 'avg':81},
{'name': 'stu2', 'math': 56, 'English': 84, 'Chinese': 74, 'avg':71},
{'name': 'stu3', 'math': 92, 'English': 83, 'Chinese': 78, 'avg':87},
{'name': 'stu4', 'math': 62, 'English': 90, 'Chinese': 88, 'avg':80}
]
# 按照平均分从高到低排序
...
students_avr = list(map(lambda item:(item['math'] + item['English'] + item['Chinese']) // 3, students))
for x in range(len(students)):
students[x]['avr'] = students_avr[x]
result = sorted(students,key=lambda item:item['avr'],reverse=True)
改
def temp(item):
item['avg'] = int((item['math']+item['English']+item['Chinese'])/3)
return item
new_students = list(map(temp,students))
print(new_students)