匿名函数、函数递归与二分法、面向过程
知识汇总:
匿名函数:没有名字的函数
map
filter
reduce
max min 求最小值
sorted
sum
递归
二分法
冒泡排序算法 比较的次数是列表的长度 - 1 for i in range(len(li) - 1):
选择排序法:
面向过程编程:
|
匿名函数
概念:
1.什么是匿名函数:
def 定义的是有名函数:特点是可以通过名字重复调用
def func(): # func=函数的内存地址
匿名函数就是没有名字的函数:特点是只能在定义时使用一次
2.为何要用匿名函数
强调:
匿名函数的定义就相当于只产生一个变量的值,而没有绑定任何名字,所以在定义完之后就会被回收,无法重复使用,只能在定义时使用一次
(函数分为定义阶段和调用阶段,定义阶段已经将函数加载到内存)
应用:
当某一个功能仅使用一次就没有再重复使用的必要了,就应该定义成匿名函数
3.如何用匿名函数
lambda x,y:x+y ----->没有函数名,直接传参。省略return
匿名函数基本代码:
print(lambda x,y:x+y) #<function <lambda> at 0x0000000001D11E18> res=(lambda x,y:x+y)(1,2)#调用和传值 print(res) #3
内置函数:字典包含两部分,要特殊对待
正常情况下字典参与函数操作的都是键,函数返回的也是键。
内置函数中key的作用是:让值进行比较,但是返回的是字典的键
max:
salaries = { 'egon': 3000, 'alex': 100000000, 'wupeiqi': 10000, 'yuanhao': 2000 } nums=[10,-1,11,9,23] print(max(nums)) print(max(salaries.values()))#返回的是最大数值
#返回最大工资对应的人名
salaries = {
'egon': 3000,
'alex': 100000000,
'wupeiqi': 10000,
'yuanhao': 2000
}
# key=函数的内存地址: 作用是控制函数的比较的值
1.多行代码实现 def func(k): return salaries[k] print(max(salaries,key=func)) #max函数的第二个参数key # 1. 将可迭代对象salaries变成迭代器对象iter_obj # 2. next(iter_obj)得到一个人名,然后将该人名当作参数传给key指定的函数,然后调用函数将函数的返回值当作比较依据 # 3. 比较大小,取出最大值对应的人名
2.单行代码实现
#通过匿名函数更加简洁的实现求极值 print(max(salaries,key=lambda k:salaries[k])) print(min(salaries,key=lambda k:salaries[k]))
sorted排序:
#以人名进行排序
nums=[10,-1,11,9,23] print(sorted(nums)) #默认从小到大排序 [-1, 9, 10, 11, 23] print(nums) #不改变原值 salaries={ 'egon':3000, 'alex':100000000, 'wupeiqi':10000, 'yuanhao':2000 }
#key=lambda k:salaries[k]--》定义一个匿名函数,salaries[k]可以取出字典对应的value,返回给匿名函数,即要比较的是值
print(sorted(salaries,key=lambda k:salaries[k]))
print(sorted(salaries,key=lambda k:salaries[k],reverse=True))
map映射:
#在所有老师后加dsb
names = ['alex', 'wupeiqi', 'yuanhao', 'kevin', 'hu老师'] # 方式一:手动实现 new_names=[] for name in names: new_names.append(name+'dsb') print(new_names) # 方式二:列表生成式 new_names = [name + 'dsb' for name in names] print(new_names) # 方式三:map+匿名函数 res = map(lambda x: x + 'dsb', names) print(res) #<map object at 0x000000000221F080> print(list(res)) #['alexdsb', 'wupeiqidsb', 'yuanhaodsb', 'kevindsb', 'hu老师dsb']
reduce合并:
# 方式一:手动实现 res=0 for i in range(101): res+=i print(res) # 方式二:列表生成式 print(sum([i for i in range(101)])) # 方式三:reduce+匿名函数 from functools import reduce print(reduce(lambda x,y:x+y,[i for i in range(101)],100))#5150 print(reduce(lambda x,y:x+y,[i for i in range(101)]))#5050 print(reduce(lambda x,y:x+y,['h','e','l','l','o'],'----------'))#----------hello
filter过滤:
#过滤出所有不以dsb结尾的老师姓名
names=['alex_dsb','wxx_sb','kevin_sb','hu_sb','egon'] # 方式一:手动实现 new_names=[] for name in names: if name.endswith('sb'): new_names.append(name) print(new_names) # 方式二:列表生成式 new_names=[name for name in names if name.endswith('sb')] print(new_names) # 方式三:filter+匿名函数 res=filter(lambda name:name.endswith('sb'),names) print(res)#<filter object at 0x0000000001EAC320> print(list(res))#['alex_dsb', 'wxx_sb', 'kevin_sb', 'hu_sb']
递归函数
概念:
1.什么是递归函数
函数的递归调用时函数嵌套调用的一种特殊形式,
特殊在调用一个函数的过程又直接或者间接地调用了该函数本身
递归的本质就是一个循环的过程,
但是递归必须满足两个原则:
1.每进入下一层递归,问题的规模必须有所减少
2.递归必须要有一个明确的结束条件或者说有一个明确的进入下一层递归的条件
并且递归有两个明确的阶段
1.回溯:一层一层的递归调用下去
2.递推:在某一层结束掉递归,然后一层一层返回
2.为何要用递归
在某些情况下,基于递归来使用重复的过程比while循环更加简单
直接调用和间接调用(非递归):
#直接 def f1(): print('from f1') f1() f1() #间接 def f2(): print('from f2') f1() def f1(): print('from f1') f2() f1()
递归举例:
#推断第5个人的年龄,第4个人比第5个小两岁,。。。,第一个人为18岁
age(5)=age(4)+2 age(4)=age(3)+2 age(3)=age(2)+2 age(2)=age(1)+2 age(1)=18 age(n)=age(n-1)+2 # n>1 age(1)=18 # n=1
#用函数表示
def age(n):
if n == 1:
return 18
return age(n-1)+2
res=age(5)
print(res) #26
打印列表中的数字:
list1=[1,[2,[3,[4,[5,[6,[7,[8,[9,]]]]]]]]] def func(l): for item in l: if type(item) is list: # 将item当作一个新列表传给功能本身 func(item) else: print(item) func(list1)
二分法:算法,高效解决问题的思路
#原始的方法:查询次数多
nums=[1,13,15,23,27,31,33,57,73,81,93,94,97,101] # 从小到大排列的数字列表
for num in nums: if 58 == num: print('find it') break else: print('not exists') #二分法:效率高,节省内存 nums = [1, 13, 15, 23, 27, 31, 33, 57, 73, 81, 93, 94, 97, 101] # 从小到大排列的数字列表 def binary_search(find_num,nums): print(nums) if len(nums) == 0: print('not exists') return # 功能 mid_index = len(nums) // 2 if find_num > nums[mid_index]: # in the right nums=nums[mid_index+1:] # 重新运行功能,传入新列表 binary_search(find_num,nums) elif find_num < nums[mid_index]: # in the left nums=nums[:mid_index] # 重新运行功能,传入新列表 binary_search(find_num,nums) else: print('find it') # binary_search(97,nums) binary_search(95,nums)
面向过程编程:
核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么后干什么...
基于该思想编写程序脑子里应该始终思考过程二字,就好比在设计一条流水线,是一种机械式的思维方式
优点:复杂的问题的流程化,进而简单化
缺点:扩展性差