python基础系列 —— 迭代器与内置高阶函数

目录

一、迭代器

1、基本概念

2、如何定义一个迭代器

3、如果判断对象是否是迭代器

4、如何重置迭代器

5、如何调用迭代器

二、生成器

三、高阶函数

1、map函数 

2、filter函数

3、reduce函数

4、sorted函数


一、迭代器

1、基本概念

    迭代:是一个重复的过程,每次重复都是基于上一次的结果而继续,单纯的重复不是迭代。

    可迭代对象:是指任何可以使用for循环遍历其元素的对象;常见的可迭代对象包括列表、元组、字符串和字典等;所有可迭代对象都有一个__iter__()方法。

setvar = {"a",1,"b",2}
for i in setvar:
	print(i)

res = dir(setvar)
print(res)

     迭代器:迭代器是可以实现对集合从前向后依次遍历的一个对象;Python中所有可迭代对象都有一个__iter__()方法,该方法返回一个迭代器对象。这个迭代器对象具有__next__()方法,用于逐个返回序列中的下一个值。当没有更多值可供返回时,__next__()会引发StopIteration异常

        Python迭代器主要解决的问题是如何遍历一个容器(例如列表、元组、字典等)中的所有元素,而不需要了解其内部实现细节。通过使用迭代器,我们可以逐个访问容器中的每个元素,并在需要时停止遍历。这使得代码更加简洁和可读,并且减少了出错的可能性。此外,迭代器还可以用于处理大型数据集或无限序列等情况下进行懒惰计算,从而提高程序效率和性能。

setvar =  {"a",1,"b",2}
it = iter(setvar) 
print(it)
print(dir(it))

    关联:可迭代对象 和 迭代器之间的关系: 从不可被直接获取 => 可被直接获取的过程。如果是一个可迭代对象,不一定是一个迭代器,如果是一个迭代器,一定是一个可迭代对象。可以通过dir()方法判断是否是迭代器。

2、如何定义一个迭代器

    通过iter()方法定义

"""
	(1)iter(可迭代对象)
	(2)可迭代对象.__iter__()
"""
setvar =  {"a",1,"b",2}
it = iter(setvar) 
print(it) # iterator

3、如果判断对象是否是迭代器

    通过三方包Iterator,Iterable判断

from collections import Iterator,Iterable
"""
    from 从哪里...  import 引入
    Iterator 迭代器类型 Iterable 可迭代对象
"""
# 判断setvar是否为可迭代对象
setvar = {"a","b","c"}
res = isinstance(setvar, Iterable)
print(res)

# 判断range是否为迭代器
it = iter(range(5))
res = isinstance(it,Iterator)
print(res)

4、如何重置迭代器

    因为迭代器是不可逆的,重置需要重新调用

"""
next调用,单项不可逆,一条路走到黑
"""
it = iter(setvar)
res = next(it)
print(res)

5、如何调用迭代器

    (1) next(迭代器)
    (2)迭代器.__next__()
    迭代器通过next方法调用时,是单向不可逆的过程

# 1.通过next获取迭代器中的数据
setvar = {"a", "b", "c"}
it = iter(setvar)
print(next(it))
print(next(it))
print(next(it))

# 2.通过for循环,遍历迭代器
print("<========>")
it = iter(range(6))
for i in it:
    print(i)
print("<========>")
# 3.for 和 next 配合调用迭代器
it = iter(range(100000))
for i in range(10): # 只调用前10个,0-9
    res = next(it)
    print(res)

print("<===>")
for i in range(10): # 没有重置,继续从10开始调用
    res = next(it)
    print(res)

二、生成器

        Python生成器主要解决的问题是如何在需要时按需生成数据,而不需要一次性将所有数据都存储在内存中。通过使用生成器,我们可以定义一个函数或表达式来产生序列中的每个元素,并且只有当需要访问该元素时才会计算它。这使得代码更加简洁和可读,并且减少了出错的可能性。此外,生成器还可以用于处理大型数据集或无限序列等情况下进行懒惰计算,从而提高程序效率和性能。

# ### 生成器函数
"""
# yield 类似于 return
共同点在于:执行到这句话都会把值返回出去
不同点在于:yield每次返回时,会记住上次离开时执行的位置 , 下次在调用生成器 , 会从上次执行的位置往下走,而return直接终止函数,每次重头调用.
yield 6 和 yield(6) 2种写法都可以 yield 6 更像 return 6 的写法 推荐使用
"""

# 1.生成器的好处是即使有1000个元素,调用时只需要先取5个再取3个,减少内存占用
def mygen():
    for i in range(1,1000):
        yield "号码%s" % (i)

# 初始化生成器函数 -> 生成器对象 -> 简称生成器
gen = mygen()

# for + next 调用生成器
for i in range(5):
	res = next(gen)
	print(res)

print("********************************")
for i in range(3):
	res = next(gen)
	print(res)


# 2.send 可以发送数据,发送给上一个yield
"""
### send
# next和send区别:
	next 只能取值
	send 不但能取值,还能发送值
# send注意点:
	第一个 send 不能给 yield 传值 默认只能写None
	最后一个yield 接受不到send的发送值
"""
def mygen():
	print("start")
	res = yield 111
	print(res)

	res = yield 222
	print(res)

	res = yield 333
	print(res)

	print("end")


# 初始化生成器函数 -> 返回生成器对象 -> 简称生成器
gen = mygen()

# 第一次调用
# 第一次只能默认发送None,因为第一次没有上一个yield
val = gen.send(None)
print(val)
print("***")
# 第二次调用
val = gen.send(444)
print(val)
print("***")
# 第三次调用
val = gen.send(555)
print(val)
print("***")


"""
无论是next 还是 send 都可以调用生成器里面的数据
send 不但可以调用,还可以给yield 发送值

第一次调用send , 只能发送None ,因为还没有遇到yield
代码从上到下执行, print("start") 遇到 res = yield 111
记录当前代码执行的状态87行,把111值返回,等待下一次调用
外面的val = 111  print(111)

# 第二次调用send ,把444发送给上一次保存的位置87行
yield 进行接收 res = 444  87行往下执行 print(444) 遇到 res = yield 222
记录当前代码执行的状态90行,把222值返回,等待下一次调用
外面的val = 222 print(222)

# 第三次调用send ,把555发送给上一次保存的位置90行
yield 进行接收 res = 555  90行往下执行 print(555) 遇到 res = yield 333
记录当前代码执行的状态93行,把333值返回,等待下一次调用
外面的val = 333 print(333)

# 第四次调用send , 把555发送给上一次保存的位置93行
yield 进行接收 res = 666  93行往下执行 print(666)  print("end")
没有任何yield 返回数据 , 出现StopIteration 
到此程序彻底结束.
"""


# 3.yield from : 将一个可迭代对象变成一个迭代器返回	

def mygen():
	lst = ["魏小林","陈宁波","朱胜"]
	yield from lst
gen = mygen()
print(next(gen))
print(next(gen))
print(next(gen))




# 4.案例: 用生成器来写一个斐波那契数列

"""
生成器应用在大数据的场景中,按照需求依次取值,
切记不要直接迭代生成器所有数据
一旦数据量较大,类似于死循环
"""
# 1 1 2 3 5 8 13 21 34 55 ..... 

def mygen(maxlength):
	a = 0
	b = 1
	
	i = 0
	while i < maxlength:
		# print(b)
		yield b
		# 当前值 = 上上个值 + 上一个值
		a,b = b,a+b
		i+=1

gen = mygen(50)
# 按照需求量进行取值
for i in range(30):
	print(next(gen))

三、高阶函数

    高阶函数 : 能够把函数当成参数传递的就是高阶函数,主要包括map、filter、reduce、sorte。

1、map函数 

map(func,iterable)

功能:
    把iterable里面的数据一个一个拿出来,放到func函数中进行处理,把处理的结果扔到迭代器中,返回迭代器
参数:
    func 自定义函数 或者 内置函数
    iterable 可迭代对象 (容器类型数据 range 迭代器)
返回值:
    迭代器
备注:
    主要做批处理,把iterable里面的数据根据自己的规则进行处理,最终输出。
# 1.转换列表的字符串为数字
# ["1","2","3","4"] => [1,2,3,4]

lst = ["1","2","3","4"]
print(lst)
it = map(int,lst)
lst = list(it)
print(lst)

# 代码分析:map函数首先拿出列表当中的"1",扔到int函数当中处理,处理的结果扔到迭代器当中,依次遍历。然后通过list强转迭代器 ,返回一个列表。



# 2.处理列表的元素,整体变为二次方
# [1,2,3,4] => [1,4,9,16]

lst = [1,2,3,4]

# map方法一,自定义处理逻辑函数
def func(n):
	return n ** 2
it = map(func,lst)
# map方法二,利用匿名函数简化代码(推荐)
it = map( lambda n : n ** 2 , lst )

# 强转成列表,瞬间拿到所有数据
print(list(it))



# 3.根据字典的k或者v,取出对应的值
# dic = {97:"a",98:"b",99:"c"} 给你["a","b","c"] => 返回 [97,98,99]

lst = ["a","b","c"]
dic = {97:"a",98:"b",99:"c"}

def func(n):
    for k,v in dic.items():
        if n == v:
			return k
it = map(func,lst)
print(list(it))

2、filter函数

filter(func,iterable)

功能:
	在自定义的函数中,过滤数据
	如果返回True  代表保留数据
	如果返回False 代表舍弃该数据
参数:
	func 自定义函数
	iterable 可迭代性数据(容器类型数据 range对象 迭代器)
返回值:
	迭代器
备注:
    这个函数f的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。
# 提取列表所有的奇数
# 1.[1,2,3,4,5,6,7,8] => [1, 3, 5, 7]


lst = [1, 2, 3, 4, 5, 6, 7, 8]


def func(n):
    if n % 2 == 0:
        return False
    else:
        return True


it = filter(func, lst)

# 2.for
print("遍历输出所有元素")
it = filter(func, lst)
for i in it:
    print(i)

# 3.for + next
print("遍历输出前两个元素")
it = filter(func, lst)
for i in range(2):
	print(next(it))

# 4.list强转,瞬间得到所有数据
print("将所有结果强转为list")
it = filter(func, lst)
lst = list(it)
print(lst)

# 改写成lambda 表达式
print("lambda简化代码,结果不变")
lst = [1, 2, 3, 4, 5, 6, 7, 8]
it = filter(lambda n: True if n % 2 == 1 else False, lst)
print(list(it))

3、reduce函数

reduce(func,iterable)

功能:
    一次性从iterable当中拿出2个值,扔到func函数中进行处理,把运算的结果在和iterable的第三个值继续扔到func中做运算
	 ... 以此类推 
	 最后返回计算的结果
参数:
	func 自定义函数
	iterable 可迭代性数据(容器类型数据 range对象 迭代器)
返回值:
	最后计算的结果
备注:
	类似聚合函数,利滚利
from functools import reduce

# 1.计算列表 [2, 4, 5, 7, 12] 中所有元素的乘积,然后再将结果与初始值 2 相乘
# 2*4*5*7*12 再*2

def prod(x, y):
    return x * y
print(reduce(prod, [2, 4, 5, 7, 12], 2))

# 解释:reduce() 函数会对序列中的每个元素依次执行 prod() 函数,并将前一次调用的结果作为下一次调用时的第一个参数传入。最终得到所有元素相乘的结果。


# 2.将列表转化为数字
# [5,4,8,8] => 5488

lst = [5,4,8,8]
def func(x,y):
	return x*10 + y
res = reduce(func,lst)
print(res, type(res))

"""
先从lst拿出前两个数据,5和4,扔到func当中进行运算 5 * 10 + 4 = 54
拿54 和 容器中第三个元素 8 , 扔到func当中进行运算 54 * 10 + 8 = 548 
拿548 和 容器中第四个元素 8 , 扔到func当中进行运算 548 * 10 + 8 = 5488
最后把5488 直接返回,程序结束.
"""

# 优化成lambda表达式写法
print( reduce(lambda x,y : x * 10 + y,lst) )

4、sorted函数

sorted(iterable,reverse=False,key=函数)

功能:  
	对数据进行排序
参数: 
    iterable  : 具有可迭代性的数据(迭代器,容器类型数据,可迭代对象)
    reverse   : 是否反转 默认为False 代表正序, 改成True 为倒序
    key       : 指定函数 内置或自定义函数
返回值:
	返回排序后的数据
备注:
    可以对列表、元组等可迭代对象进行排序
# 1.对列表进行升序排列

lst = [3, 2, 4, 1]
print(sorted(lst))   # 输出:[1, 2, 3, 4]

# 2.对元组进行降序排列

tpl = (5, 7 ,6 ,8)
print(sorted(tpl, reverse=True))   # 输出:[8, 7 ,6 ,5]

# 3.按字符串长度对列表中的字符串进行升序排列

lst = ['apple', 'banana', 'pear', 'orange']
print(sorted(lst,key=len))   # 输出:['pear', 'apple', 'banana', 'orange']

# 4.对数组按照绝对值排序
lst = [3, -2, 4, 1, -10]
print(sorted(lst,key=abs))   # 输出:[1, -2, 3, 4, -10]

猜你喜欢

转载自blog.csdn.net/weixin_39855998/article/details/129382422
今日推荐