文章目录
高阶函数(map filter reduce sorted)
高阶函数的定义:能够把函数当成参数传递的就是高阶函数
常用的四大高阶函数:map filter reduce sorted
map(处理数据)
map(func,Iterable)
功能:处理数据
把Iterable中的数据一个一个拿出来,扔到func函数中做处理
把处理之后的结果放到迭代器当中,最后返回迭代器
参数:
func : 自定义函数 或 内置函数
Iterable : 可迭代性数据(容器类型数据 range对象 迭代器)
返回值:
迭代器
示例1:将[“1”,“2”,“3”,“4”]转化成[1,2,3,4]
常规写法
lst = ["1","2","3","4"]
# 常规写法
lst_new = []
for i in lst:
lst_new.append(int(i))
print(lst_new)
用map改造的写法
# map改造
it = map(int,lst) # it是一个map对象
print(list(it)) # [1,2,3,4]
代码解析`
map(int,lst)的实现过程:
首先把"1" 扔到int当中做处理,将强转后的结果扔到迭代器中
然后把"2" 扔到int当中做处理,将强转后的结果扔到迭代器中
然后把"3" 扔到int当中做处理,将强转后的结果扔到迭代器中
然后把"4" 扔到int当中做处理,将强转后的结果扔到迭代器中
最终返回迭代器
获取迭代器中的数据的方法:1.next() 2.for循环遍历 3.for+next 4.list(it)强转
示例2:[1,2,3,4] => [2,8,24,64]
# map改造
'''参数和返回值return一定要写'''
def func(n):
return n << n
lst = [1,2,3,4]
it = map(func,lst)
print(list(it)) # [2, 8, 24, 64]
# lambda + map
it = map(lambda n : n << n , lst)
print(list(it))
示例3:dic = {97:“a”,98:“b”,99:“c”} # [“a”,“b”,“c”] => ascii [97,98,99]
# map改造
def func(n):
# 原字典
dic = {97:"a",98:"b",99:"c"}
# 新字典
dic_new = {}
# 遍历原字典
for k,v in dic.items():
# 更换键值对
dic_new[v] = k
print(dic_new) # {'a': 97, 'b': 98, 'c': 99}
# 通过键来获取值
return dic_new[n]
lst = ["a","b","c"]
it = map(func,lst)
print(list(it))
filter(过滤数据)
filter(func,iterable)
功能: 过滤数据
return True 当前这个数据保留
return False 当前这个数据舍弃
参数:
func : 自定义函数
iterable : 可迭代型数据(容器类型数据,range对象,迭代器)
返回值:
迭代器
lst = [1,2,3,4,5,6,7,8,9,10]
# 常规写法
lst_new = []
for i in lst:
if i % 2 == 0:
lst_new.append(i)
print(lst_new)
# filter改写
def func(i):
if i % 2 == 0:
return True
else:
return False
it = filter(func,lst)
# filter + lambda 改写
it = filter(lambda i : True if i % 2 == 0 else False , lst )
print(list(it))
reduce(计算数据)
reduce(func,iterable)
功能:计算数据
先把iterable中的前两个值拿出来,扔到func当中做运算,
把计算的结果和iterable中的第三个元素在扔到func当中做运算,
再把结果算出来,和第四个元素做运算,以此类推
直到所有结果运算完毕.返回该结果
参数:
func : 自定义函数
iterable : 可迭代型数据(容器类型数据,range对象,迭代器)
返回值:
计算之后的结果
示例1:lst = [5,4,8,8] => 整型5488
常规写法1
strvar = ""
for i in lst:
strvar += str(i)
print(strvar , type(strvar))
res = int(strvar)
print(res , type(res))
常规写法2
from collections import Iterator,Iterable
lst = [5,4,8,8]
it = iter(lst)
print(isinstance(it , Iterator)) # True
print(isinstance(it , Iterable)) # True
num1 = next(it) # 5
num2 = next(it) # 4
num = num1 * 10 + num2 # 54
for i in it:
num = num * 10 + i # 54*10+8=548 548*10+8=5488
print(num, type(num)) # 5488 <class 'int'>
reduce改造]
def func(x,y):
return x*10 + y
lst = [5,4,8,8]
res = reduce(func,lst)
print(res , type(res))
# reduce+lambda:
res = reduce(lambda x,y:x*10+y,lst)
print(res)
reduce(func,lst)实现的过程
先拿出5和4两个元素,扔到func当中做运算,结果是54
在拿54和8两个元素,扔到func当中做运算,结果548
在拿548和8两个元素,扔到func当中做运算,结果5488
返回最终的结果: 5488 程序结束
示例2:“789”=>789 禁止使用int强制转换
def func1(x,y):
return x*10 + y
def func2(n):
dic = {"0":0,"1":1,"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9}
return dic[n]
it = map(func2,"789") # [7,8,9]
res = reduce(func1,it)
print(res,type(res))
sorted(排序)
sorted(iterable,key=函数,reverse=False)
功能:排序
参数:
iterable:可迭代型数据(容器类型数据,range对象,迭代器)
key :指定自定义函数或内置函数
reverse :代表升序或者降序 , 默认是升序(从小到大排序) reverse=False
返回值:
排序后的结果
# 1.默认是从小到大排序
lst = [1,2,3,4,5,-90,-4,-1,100]
res = sorted(lst)
print(res)
# 2.reverse 从大到小排序
res = sorted(lst,reverse=True)
print(res)
# 3.指定函数进行排序
# 按照绝对值排序 abs
lst = [-10,-1,3,5]
res = sorted(lst,key=abs)
print(res)
# 4.使用自定义函数进行排序
lst = [19,21,38,43,55]
def func(n):
return n % 10
lst = sorted(lst,key=func)
print(lst)
sort和sorted的区别
(1) sorted可以排序一切容器类型数据, sort只能排列表
(2) sorted返回的是新列表,sort是基于原有的列表进行修改
(3) 推荐使用sorted
列表/集合/字典/推导式
概念
推导式的定义: 通过一行循环判断,遍历一系列数据的方式
推导式的语法:
val for val in Iterable
三种方式:
[val for val in Iterable]
{val for val in Iterable}
{k:v for k,v in Iterable}
列表推导式
单循环推导式
将[1,2,3,4,5] -> [3,6,9,12,15]
# 单循环推导式 [1,2,3,4,5] -> [3,6,9,12,15]
lst = [1,2,3,4,5]
lst_new = []
for i in lst:
res = i * 3
lst_new.append(res)
print(lst_new)
# 改写成推导式
lst = [i*3 for i in lst]
print(lst)
带有判断条件的单循环推导式
# 带有判断条件的单循环推导式 (只能是单项分支,接在for后面)
lst = [1,2,3,4,5,6,7,8]
lst_new = []
for i in lst:
if i % 2 == 1:
lst_new.append(i)
print(lst_new)
# 改写成推导式
lst = [i for i in lst if i % 2 == 1]
print(lst)
双循环推导式
# 双循环推导式
lst1 = ["A","B","C","D"]
lst2 = ["X","Y","Z","Q"]
# "谁"❤"谁"
lst_new = []
for i in lst1:
for j in lst2:
strvar = i + "❤" + j
lst_new.append(strvar)
print(lst_new)
# 改写成推导式
lst = [i + "❤" + j for i in lst1 for j in lst2]
print(lst)
带有判断条件的多循环推导式
# 带有判断条件的多循环推导式
lst_new = []
for i in lst1:
for j in lst2:
if lst1.index(i) == lst2.index(j):
strvar = i + "❤" + j
lst_new.append(strvar)
print(lst_new)
# 改写成推导式
lst = [ i + "❤" + j for i in lst1 for j in lst2 if lst1.index(i) == lst2.index(j) ]
print(lst)
集合推导式
关于集合推导式的一个示例:
1.集合有自动去重的效果
2.用三元表达式+推导式即可实现
"""
案例:
满足年龄在18到21,存款大于等于5000 小于等于5500的人,
开卡格式为:尊贵VIP卡老x(姓氏),否则开卡格式为:普通用户卡老x(姓氏)
把开卡的种类统计出来
"""
listvar = [
{"name":"彭云飞","age":18,"money":10000},
{"name":"夏圣钦","age":19,"money":5100},
{"name":"陈正正","age":20,"money":4800},
{"name":"王添龙","age":21,"money":2000},
{"name":"万潇阳","age":18,"money":20}
]
# 常规写法
setvar = set()
for i in listvar:
if 18 <= i["age"] <= 21 and 5000 <= i["money"] <= 5500:
res = "尊贵VIP卡老" + i["name"][0]
else:
res = "普通用户卡老" + i["name"][0]
setvar.add(res)
print(setvar)
# 改写成集合推导式
# {三元运算符 + 推导式}
setvar = { "尊贵VIP卡老" + i["name"][0] if 18 <= i["age"] <= 21 and 5000 <= i["money"] <= 5500 else "普通用户卡老" + i["name"][0] for i in listvar }
print(setvar)
字典推导式
enumerate
功能:
枚举 ; 将索引号和iterable中的值,一个一个拿出来配对组成元组放入迭代器中
参数:
iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range)
start: 可以选择开始的索引号(默认从0开始索引)
返回值:迭代器
enumerate形成字典推导式示例:
from collections import Iterator
lst = ["东邪","西毒","南帝","北丐"]
# 基本使用
it = enumerate(lst) # [(0, '东邪'), (1, '西毒'), (2, '南帝'), (3, '北丐')]
print(isinstance(it,Iterator))
# for + next
for i in range(4):
print(next(it))
# list
"""start可以指定开始值,默认是0"""
it = enumerate(lst,start=1)
print(list(it)) # [(1, '东邪'), (2, '西毒'), (3, '南帝'), (4, '北丐')]
# enumerate 形成字典推导式 变成字典
dic = { k:v for k,v in enumerate(lst,start=1) }
print(dic) # {1: '东邪', 2: '西毒', 3: '南帝', 4: '北丐'}
# dict 强制变成字典
dic = dict(enumerate(lst,start=1))
print(dic) # {1: '东邪', 2: '西毒', 3: '南帝', 4: '北丐'}
zip
ip(iterable, ... ...)
功能:将多个iterable中的值,一个一个拿出来配对组成元组放入迭代器中
参数:iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range)
返回值: 迭代器
特征:如果找不到对应配对的元素,当前元素会被舍弃
lst1=["Fly","1dao","Hurt","Mojo"]
lst2=["Snow","Song","Giao"]
lst3=["770","JieJ"]
it = zip(lst1,lst2,lst3)
print(list(it)) # [('Fly', 'Snow', '770'), ('1dao', 'Song', 'JieJ')]
# zip形成字典推导式 变成字典
lst1=["Fly","1dao","Hurt","Mojo"]
lst2=["Snow","Song","Giao"]
dic={k:v for k,v in zip(lst1,lst2)}
print(dic) # {'Fly': 'Snow', '1dao': 'Song', 'Hurt': 'Giao'}
# dict强制变为字典
dic = dict(zip(lst1,lst2))
print(dic) # {'Fly': 'Snow', '1dao': 'Song', 'Hurt': 'Giao'}
递归函数
定义
递归函数的定义 : 自己调用自己的函数就是递归
递-去-归-回 一去一回就是递归
简单的递归例子
# 1.一个简单的递归例子
def digui(n):
print(n,"<====1===>")
if n > 0:
digui(n-1)
print(n,"<====2===>")
digui(5)
"""
# 代码解析:
去的过程:
n = 5 print(5,"<====1===>") 5>0 条件成立-> digui(5-1) => digui(4) 代码阻塞在第13行
n = 4 print(4,"<====1===>") 4>0 条件成立-> digui(4-1) => digui(3) 代码阻塞在第13行
n = 3 print(3,"<====1===>") 3>0 条件成立-> digui(3-1) => digui(2) 代码阻塞在第13行
n = 2 print(2,"<====1===>") 2>0 条件成立-> digui(2-1) => digui(1) 代码阻塞在第13行
n = 1 print(1,"<====1===>") 1>0 条件成立-> digui(1-1) => digui(0) 代码阻塞在第13行
n = 0 print(0,"<====1===>") 0>0 条件不成立 print(0,"<====2===>")
当前这层空间代码已经执行结束
此刻触发回的过程
n = 1 从上一次13行的代码阻塞位置,继续向下执行 print(1,"<====2===>")
n = 2 从上一次13行的代码阻塞位置,继续向下执行 print(2,"<====2===>")
n = 3 从上一次13行的代码阻塞位置,继续向下执行 print(3,"<====2===>")
n = 4 从上一次13行的代码阻塞位置,继续向下执行 print(4,"<====2===>")
n = 5 从上一次13行的代码阻塞位置,继续向下执行 print(5,"<====2===>")
到此,递归函数彻底执行结束.
5 4 3 2 1 0 0 1 2 3 4 5
"""
递归的特点和注意点
一.递归是一去一回的过程,
调用函数时,会开辟栈帧空间,函数执行结束之后,会释放栈帧空间
递归实际上就是不停的开辟和释放栈帧空间的过程
每次开辟栈帧空间,都是独立的一份,其中的资源不共享
二.触发回的过程
1.当最后一层栈帧空间全部执行结束的时候,会触底反弹,回到上一层空间的调用处
2.遇到return,会触底反弹,回到上一层空间的调用处,
3.写递归时,必须给与递归跳出的条件,否则会发生内存溢出,蓝屏死机的情况.
如果递归层数过多,不推荐使用递归
递归练习
用递归计算n的阶乘
# 常规方法
# 5! = 5*4*3*2*1
def func(n):
total = 1
for i in range(n,0,-1):
total *= i
return total
res = func(5)
print(res)
# 递归写法
def jiecheng(n):
if n <= 1:
return 1
return n*jiecheng(n-1)
res = jiecheng(5)
print(res)
"""
return 后面的表达式,一定是先计算完在返回
# 代码解析:
# 去的过程:
n = 5 return 5*jiecheng(5-1) => 5 * jiecheng(4)
n = 4 return 4*jiecheng(4-1) => 4 * jiecheng(3)
n = 3 return 3*jiecheng(3-1) => 3 * jiecheng(2)
n = 2 return 2*jiecheng(2-1) => 2 * jiecheng(1)
n = 1 return 1
# 回的过程:
n = 2 return 2*jiecheng(2-1) => 2 * jiecheng(1) => 2 * 1
n = 3 return 3*jiecheng(3-1) => 3 * jiecheng(2) => 3 * 2 * 1
n = 4 return 4*jiecheng(4-1) => 4 * jiecheng(3) => 4 * 3 * 2 * 1
n = 5 return 5*jiecheng(5-1) => 5 * jiecheng(4) => 5 * 4 * 3 * 2 * 1
return 5 * 4 * 3 * 2 * 1 => return 120
额外解析:
jiecheng(1) => 1
jiecheng(2) => 2*jiecheng(1) => 2*1
jiecheng(3) => 3*jiecheng(2) => 3*2*1
jiecheng(4) => 4*jiecheng(3) => 4*3*2*1
jiecheng(5) => 5*jiecheng(4) => 5*4*3*2*1
"""
尾递归
定义
自己调用自己,并且非表达式
计算的结果要在参数当中完成.
尾递归无论调用多少次函数,都只占用一份空间,但是目前cpython不支持.
def jiecheng(n,endval):
if n <= 1:
return endval
return jiecheng(n-1,endval*n)
res = jiecheng(5,1)
print(res)
"""
# 代码解析:
去的过程
n=5 , endval=1 return jiecheng(5-1,endval*5) => jiecheng(4,1*5)
n=4 , endval=1*5 return jiecheng(4-1,endval*4) => jiecheng(3,1*5*4)
n=3 , endval=1*5*4 return jiecheng(3-1,endval*3) => jiecheng(2,1*5*4*3)
n=2 , endval=1*5*4*3 return jiecheng(2-1,endval*2) => jiecheng(1,1*5*4*3*2)
n=1 , endval=1*5*4*3*2 return 120
回的过程:
n=2 return 120
n=3 return 120
n=4 return 120
n=5 return 120
因为最后一层空间的返回值就是第一层空间的返回值,所有在使用尾递归的时候
不需要考虑回的逻辑过程,就能解决问题.推荐使用.
"""
可以对尾递归计算n的阶乘例子进行优化,因为在jiecheng()函数中,有两个参数,这样用户有可能会乱传参数,为了防止乱传参数。设计了如下两种方法解决:
# 优化1
def jiecheng(n,endval=1):
if n <= 1:
return endval
return jiecheng(n-1,endval*n)
res = jiecheng(5)
print(res,"<111>")
# 优化2
"""为了避免用户乱传参数,把endval这个参数隐藏起来"""
def outer(n):
def jiecheng(n,endval=1):
if n <= 1:
return endval
return jiecheng(n-1,endval*n)
return jiecheng(n) # jiecheng(n-1,endval*n)
res = outer(5)
print(res)
递归计算斐波那契数列
def feb(n):
# 递归跳出的条件
if n <= 2: # n == 1 or n == 2 => 1
return 1
return feb(n-1) + feb(n-2)
res = feb(5)
print(res)