day23 匿名函数lambda、迭代器、高阶函数(reduce、sorted、filter)

1.匿名函数

用一句话来表达:只有返回值的函数,叫做匿名函数。

1.1不带有参数的lambda表达式

语法:
lambda 参数 : 返回值

def func():
    return "今天要下雨,天气挺冷"

# 定义一个lambda表达式
func = lambda :  "今天要下雨,天气挺冷"
res = func()
print(res)
# 今天要下雨,天气挺冷

1.2带有参数的lambda表达式

# 情况1:
def
func(n): return type(n) func = lambda n : type(n) res = func(3) print(res)
#<class 'int'>
# 情况2
func = lambda n : print(n)
res = func(13)
print(res)

  #13
  #None

分析:首先lambda是一个匿名函数,print(13)为匿名函数中的返回值部分,由于print(13)只是一个输出没有返回值,故最后的结果返回的是13.
#print(print(15))个人理解就是返回值就是(经过表达式计算后的函数结果)
# def func()
  print(13)
# return xx 匿名函数其实需要的是xx不是print(13),把返回值(最终返回的表达式)代入参数然后打印出来。

1.3带有条件分支的 lambda表达式

三目运算符:    
语法:
真值 if 条件表达式 else 假值
如果条件表达式是真的,返回真值
如果条件表达式是假的,返回假值(else后面跟的值)
res = 15 if 5>3 else 6
print(res) # 15

def func(n):
    if n % 2 == 0:
        return "偶数"
    else:
        return "奇数"

n = 15
res = "偶数" if n % 2 == 0 else "奇数"
print(res)#奇数

func = lambda n : "偶数" if n % 2 == 0 else "奇数"
res = func(15)#奇数
print(res)

# 把两个值当中较大的数返回出来
def func(x,y):
    if x>y:
        return x
    else:
        return y
        
func = lambda x,y :x if x>y else y 
res = func(133,19)
print(res)

2.高阶函数

定义:能够把函数当做参数传递的就是高阶函数

2.1map()

map(func,iterable)
功能:
    把iterable里面所有数据 一一的放进到func这个函数中进行操作 ,把结果扔进迭代器
参数:
    func  内置或自定义函数
    iterable 具有可迭代性的数据 ([迭代器],[容器类型的数据],[range对象])
返回值: 
    返回最后的迭代器

# 1. ["1","2","3","4"] => [1,2,3,4]

第一步,普通写法。

普通写法:
lst = []
for i in listvar:
    res = int(i)
    lst.append(res)
print(lst)

 第二步,由于listvar是一个可迭代性数据,那么我们就使用map函数来做。

from collections import Iterator, Iterable
it = map(int, listvar)
print(isinstance(it, Iterator))
print(isinstance(it, Iterable))
print(it)

 #True
 #True
 #<map object at 0x0000000001EB0CF8>

 第三步,得到了迭代器it怎么去获取迭代器中的值,方法有三种。

# (1)使用for循环遍历迭代器
'''
for i  in  it:
    print(i)
'''
# (2) 使用next获取迭代器中的数据
'''next调用迭代器中的数据,是单项不可逆,一条路走到黑'''
'''
res = next(it)
print(res)
res = next(it)
print(res)
res = next(it)
print(res)
res = next(it)
print(res)
'''
# (3) 使用list强转迭代器(瞬间得到迭代器中的所有数据)(将罐子打破瞬间爆炸)
res = list(it)
print(res)
#[1, 2, 3, 4]
小结:都是1,2,3,4 方向不可逆。注意迭代器中的值一旦取完之后,迭代器中没有值了。无论去使用3种办法中的哪一种方法去获取值,都会报错误。
其中next调用迭代器中的数据,也是是单项不可逆,一条路走到黑,也就是说当迭代器中没有值了,就会报错误,StopIteration。
了解可以跳过:
上面的代码最详细的解释是:
代码解析:
首先把listvar当中的第一个值1拿到func当中进行处理,返回1扔到迭代器里
然后把listvar当中的第二个值2拿到func当中进行处理,返回4扔到迭代器里
然后把listvar当中的第三个值3拿到func当中进行处理,返回9扔到迭代器里
..
依次类推,直到把列表里面的数据全部拿完为止.

 2.2 map函数表达式中,func这个函数可以是自定义也可以是内置函数,如果是自定义函数一定要有返回值。

其实从2.2的标题可以得出,和匿名函数的lambd后面返回值,也差不多,都是需要的函数返回值。lambda表达式中的返回值可理解为print(返回值)。

# 2. [1,2,3,4,5] => [1,4,9,16,25]

# 普通写法:
'''
listvar = [1,2,3,4,5]
lst = []
for i in listvar:
    res = i ** 2
    lst.append(res)
print(lst)
'''
listvar = [1, 2, 3, 4, 5]
def func(n):
    return n**2

it = map(func,listvar)
print(isinstance(it, Iterator))
listvar = list(it)
print(listvar)
#True

  #[1, 4, 9, 16, 25]

# 3. {97:"a",98:"b",99:'c',100:'d',101:"e"}  {"c","a","b"} => [99,97,98]
'''
# 普通写法:
dic = {97:"a",98:"b",99:'c',100:'d',101:"e"}
dic2 = {}
# 反转字典
for a,b in dic.items():
    dic2[b] = a
print(dic2)
lst = ["c","a","b"]
lst2 = []
#{'a': 97, 'b': 98, 'c': 99, 'd': 100, 'e': 101}
for i in lst:
    res = dic2[i]
    lst2.append(res)
print(lst2)
'''

def func(n):
    dic = {97:"a",98:"b",99:'c',100:'d',101:"e"}
    dic2 = {}
    # 反转字典
    for a,b in dic.items():
        dic2[b] = a
    #{'a': 97, 'b': 98, 'c': 99, 'd': 100, 'e': 101}
    return dic2[n]

it = map(func,["c","a","b"])
print(isinstance(it,Iterator))
lst = list(it)
print(lst)

运行结果:

  #True
  #[99, 97, 98] 

 3.reduce()

reduce(func,iterable)
功能:计算    
    先把iterable中的前两个数据拿出来,扔到func当中,
    进行计算,把计算的结果在和iterable当中的第三个数据扔到func中
    进行计算, 依次类推... ... 
    直到iterable中的数据全都拿出来为止.
参数:
    func: 内置函数 或者 自定义函数
    iterable:可迭代性数据(常用:容器类型数据,range对象,迭代器)
返回值:
    计算最终的结果

 例:

# [5,4,8,8] => 5488
# 方法一
lst = [5,4,8,8]
strvar = ''
for i in lst:
    strvar += str(i)
print(strvar,type(strvar))
res = int(strvar)
print(res,type(res))

# 方法二
'''
5*10 + 4 = 54
54*10 + 8 = 548
548*10 + 8 = 5488
'''
lst = [5,4,8,8,1,2,3,4]
it = iter(lst)
num1 = next(it) # 5
num2 = next(it) # 4
total = num1 * 10 + num2
print(total)
for i in it:
    total = total * 10 + i
print(total,type(total))
# 方法三(使用reduce)
from functools import reduce
lst = [5,4,8,8]
def func(x,y):
    return x*10+y

res = reduce(func,lst)
print(res)
'''
首先把5,4拿到func函数当中,进行运算得到54
然后把54和lst当中的第三个元素8拿到func当中进行运算得到548
然后把548和list当中的第四个元素8拿到func当中进行运算得到5488
到此,所有数据运算完毕,返回5488
'''

# "987" => 987 (不让使用int类型强转)
def func(x,y):
    return x*10+y
# ["9","8","7"]
res = reduce(func,"987")
print(res)
# '9999999999899999999998999999999989999999999899999999998999999999987' 
# "987" => [9,8,7]
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,"987")
# print(list(it))
res = reduce(func,it)
print(res,type(res))

 

 4.sorted()

sorted(iterable,reverse=False,key="函数")
功能:    排序
    把可迭代性的数据进行排序.
参数:
    iterable: 可迭代型数据(常用:容器类型数据 range对象 迭代器)
    reverse=False 从小到大排序 (升序,正序)
    reverse=True  从大到小排序 (降序,倒序)
    key = 内置函数 或者 自定义函数
返回值:
    排序后的结果

4.1 从小到大排序

listvar = [-99,13,24,0]
res = sorted(listvar)
print(res)

4.2 从大到小排序

listvar = [-99,-13,24,0]
res = sorted(listvar,reverse=True)
print(res)
#[-99, 0, 13, 24]

4.3 利用内置函数进行排序

# abs 绝对值函数
'''
res = sorted(listvar,key=abs)
print(res)

#[0, -13, 24, -99]

4.4 利用自定义函数进行排序

def func(n):
    return n % 10    

listvar = [91,23,44,19]
res = sorted(listvar,key=func)
print(res)

#[91, 23, 44, 19]

5.filter()

filter(func,iterable)
功能: 过滤数据
参数:
    func 自定义函数 (return True 保留数据,return False 舍弃数据)
    iterable : 可迭代型数据(常用:容器类型数据 range对象 迭代器)
返回值:
    迭代器

 例:

# 保留奇数,不要偶数
def func(n):
    if n % 2 == 1:        
        return True
    else:
        return False
lst = {1,2,3,3,4,4,5,65,67,7,8}
it = filter(func,lst)
from collections import Iterable, Iterator
print( isinstance(it,Iterator) )
# 使用list 强转迭代器(瞬间拿到所有数据)
res = list(it)
print(res)

# 通过lambda表达式来优化代码;
it2 = filter(lambda n :  True if n % 2 == 1 else False,lst)
print(list(it2))


运行结果:

True
[1, 3, 5, 65, 67, 7]
[1, 3, 5, 65, 67, 7]

 6.迭代器

能够被next调用,并不断返回下一个值的对象,叫迭代器(迭代器是对象)
特征:迭代器会生成惰性序列,它通过计算把值依次的返回,一边循环一边计算而不是一次性得到所有数据
优点:需要数据的时候,一次取一个,可以大大节省内存空间.而不是一股脑的把所有数据放进内存.
总结:
    1.惰性序列,节省内存空间
    2.遍历获取值得时候使用next,方向不可逆
    3.迭代器可以遍历无限量大的数据

 6.1可迭代对象

# (1)可迭代性对象
''' __iter__ '''
setvar = {"周杰伦",13,"aa",90}
for i in setvar:
    print(i)
# dir 查看数据里面的内置属性或方法
# print(dir(setvar))
print("__iter__" in dir(setvar))
# next(setvar)
"""
for循环遍历setvar这个数据时,先把setvar变成迭代器,在进行取值
"""
了解:
for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法,即在遍历之前,先调用对象的__iter__方法将其转换成一个迭代器,
然后使用迭代器协议去实现循环访问,这样所有的对象就都可以通过for循环来遍历了,而且你看到的效果也确实如此,
这就是无所不能的for循环,最重要的一点,转化成迭代器,在循环时,同一时刻在内存中只出现一条数据,极大限度的节省了内存~

6.2迭代器

可迭代对象 -> 迭代器  | 不能直接调用 -> 可直接调用
__iter__ __next__ 都包含在当前这个数据类型当中,就是迭代器
如何变成一个迭代器?
    (1)iter(可迭代型数据) (推荐)
    (2)可迭代性数据.__iter__()
    
调用迭代器时:
    (1)next 可以调用 (推荐)
    (2)__next__() 也可以调用
调用:
setvar = {"周杰伦", 13, "aa", 90}
it1 = iter(setvar)
print(it1)
# <set_iterator object at 0x0000000001E96F30>
res = next(it1)
print(res)
res = next(it1)
print(res)
res = next(it1)
print(res)
res = it1.__next__()
print(res)
# 如果调用时,超出了正常的数据范围,会报越界错误.StopIteration
# res = next(it1)
# print(res)

 #13
 #90
 #周杰伦
 #aa  

 

6.3判断是否是迭代器、可迭代对象

# 判断是否是迭代器
listvar = dir(it1)
print(listvar)
print("__iter__" in listvar and "__next__" in listvar)(不推荐使用)
# 推荐使用这个
# (3) 判断是否是迭代器或可迭代对象
# from ... import 从哪个模块 .. 引入 ...
# collections(模块) Iterator迭代器类型 Iterable可迭代对象类型
from collections import Iterator,Iterable
setvar = {"周杰伦", 13, "aa", 90}
res = isinstance(setvar, Iterator)
print(res) #Flase
res = isinstance(setvar, Iterable)
print(res) #True

# 判断range对象迭代属性

for i in range(9):
    print(i)
# res = next(range(9))
res1 = isinstance(range(9),Iterable)
print(res1)
res2 = isinstance(range(9),Iterator)
print(res2)
# True
#Flase

#把range对象变成迭代器

如果是一个迭代器,一定具备可迭代属性
如果是可迭代对象,不一定是迭代器
# iter   __iter__()
it2 = range(9).__iter__()
print(isinstance(it2,Iterator))
print(isinstance(it2,Iterable))
# True
# True
 

 6.4从迭代器中取值

# 配合for循环遍历迭代器

 
 
it2 = iter(range(9)

for i in it2:
print(i)
# 迭代器在遍历数据的时,要注意方向是单向不可逆
# next(it2)
# 0
# 1
# 2
# 3
...
# 9

迭代器在遍历数据(使用next就行取值/也可以使用for就行直接遍历/还可以使用list把罐子打碎)的时,要注意方向是单向不可逆。
使用for循环就行遍历迭代器的时候,可以控制个数,配合next使用。

# 重置迭代器之后可以重新利用for就行遍历

it2 = iter(range(9))
for i in range(3):
   res = next(it2)
   print(res)
# 0
# 1
# 2
print(next(it2)) print(next(it2)) print(next(it2))
# 3
# 4
# 5(单向不可变,取完迭代器里面的值之后,只要重置迭代器才能再次从头取值)

猜你喜欢

转载自www.cnblogs.com/longerandergou/p/10923516.html