高阶函数、列表/集合/字典/推导式、递归函数


高阶函数(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)实现的过程

先拿出54两个元素,扔到func当中做运算,结果是54
在拿548两个元素,扔到func当中做运算,结果548
在拿5488两个元素,扔到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)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值