python学习 day12_迭代器&高阶函数

迭代器

迭代器 : 能被next调用,并不断返回下一个值得对象,叫做迭代器 (迭代器是对象)

  • 概念:迭代器指的是迭代取值的工具,迭代是一个重复的过程,每次重复都是基于上一次的结果而继续,单纯的重复不是迭代
  • 特征:不依赖索引,通过next指针迭代所有数据,一次只取一个,可以大大节省空间,迭代无限量的数据

可迭代对象与迭代器的关系

(1) 可迭代对象

如果成员中含有__iter__这个方法,就是可迭代对象

  • dir 函数可以查看一个对象中所有的成员
setvar = {"a",1,"b",2}
for i in setvar:
	print(i)

res = dir(setvar)
print(res)

(2) 迭代器

  • 1.for 循环遍历数据的底层实现就是利用了迭代器,通过next方法进行调用,从而获取数据
    可迭代对象 和 迭代器之间的关系: 从不可被直接获取 => 可被直接获取的过程

  • 2.如果是一个可迭代对象,不一定是一个迭代器
    如果是一个迭代器,一定是一个可迭代对象

迭代器相关操作

(1) 如何定义一个迭代器

(1)iter(可迭代对象)
(2)可迭代对象.iter()

setvar =  {"a",1,"b",2}
it = iter(setvar)	# 转化为迭代器
print(it)			# iterator:迭代器

(2) 如何判断一个迭代器

  • 如果内置成员中 含有 iternext 两个方法,就可以判断是一个迭代器
    我们拿上面代码块的it来用
print(dir(it))
res = "__iter__" in dir(it) and "__next__" in dir(it)
print(res)	# True

(3) 如何调用一个迭代器

(1) next(迭代器)
(2)迭代器.next()

  • 迭代器通过next方法调用时,是单向不可逆的过程
res = next(it)
print(res)
res = next(it)
print(res)
res = next(it)
print(res)
res = next(it)
print(res)

# res = next(it)	在超出迭代器数据的数量时继续调用会报错
# print(res)

(4) 重置迭代器

next调用,单项不可逆,一条路走到黑

  • 重置迭代器的方法:重新赋值
it = iter(setvar)
res = next(it)
print(res)		# 再次用next调用迭代器时发现重新开始迭代

(5) 使用Iterator 和 Iterable 来判断是否是迭代器

引入模块格式:

  • from 从哪里… import 引入
    Iterator 迭代器类型 Iterable 可迭代对象

示例:

  • 判断setvar的迭代属性
from collections import Iterator,Iterable	# 引入模块


setvar = {"a","b","c"}
res = isinstance(setvar,Iterator)	# 判断是否为迭代器
print(res) # False

res = isinstance(setvar, Iterable)	# 判断是否为可迭代对象
print(res) # True
  • 判断range的迭代属性
it = range(5)
res = isinstance(it,Iterator)
print(res)		# False

res = isinstance(it,Iterable)
print(res)		# True

更多的调用方式

1.通过next获取迭代器中的数据

res = next(it)
res = next(it)
res = next(it)
res = next(it)
res = next(it)
# res = next(it) error 超出迭代器数据的数量时继续调用会报错
print(res)

2.通过for循环,遍历迭代器

for循环调用迭代器与next一样,也不可逆

it = iter(range(6))
for i in it:
	print(i)

3.for 和 next 配合调用迭代器

用for循环控制每次next调用迭代器的次数

it = iter(range(100000))
for i in range(10):
	res = next(it)		# 循环调用十次迭代器it
	print(res)

for i in range(10):
	res = next(it)		# 接着之前调用的位置继续往后调用十次
	print(res)

4.用while遍历迭代器

先了解下新语法:

try:
	<语句>       #运行别的代码
except <名字><语句>       #如果在try部份引发了'name'异常
except <名字><数据>:
	<语句>       #如果引发了'name'异常,获得附加的数据
else:
	<语句>       #如果没有异常发生

while遍历迭代器写法:

while True:
    try:
        print(next(itervar))
    except StopIteration:
        break

高阶函数 : 能够把函数当成参数传递的就是高阶函数 map filter reduce sorted

能调度别的函数为自己工作的就是函中之函——高级函数!

【map】

  • 功能:把iterable里面的数据一个一个拿出来,放到func函数中进行处理,把处理的结果扔到迭代器中,返回迭代器

格式:map(func,iterable)

参数:

  • func 自定义函数 或者 内置函数
    iterable 可迭代对象 (容器类型数据 range 迭代器)

返回值:

  • 迭代器

案例一:

  • 将列表[“1”,“2”,“3”,“4”]转化为[1,2,3,4]

常规写法:

lst = ["1","2","3","4"]
lst_new = []
for i in lst:
	res = int(i)
	lst_new.append(res)
print(lst_new)

map改写

from collections import Iterator , Iterable
it = map(int,lst)		# map改写的算法就这么一条
res = isinstance(it,Iterator)	# 判断map输出的数值是否为迭代器
print(res)	# True
"""
代码解析:
首先拿出列表当中的"1",扔到int函数当中处理,处理的结果扔到迭代器当中
首先拿出列表当中的"2",扔到int函数当中处理,处理的结果扔到迭代器当中
首先拿出列表当中的"3",扔到int函数当中处理,处理的结果扔到迭代器当中
首先拿出列表当中的"4",扔到int函数当中处理,处理的结果扔到迭代器当中
最后把迭代器返回
"""
  • 然后如何取出迭代器中的元素组成列表呢,就有了下面的课题

获取迭代器中的元素的方法:

(1) next 获取迭代器中的元素
res = next(it)
print(res)
res = next(it)
print(res)
res = next(it)
print(res)
res = next(it)
print(res)
# res = next(it)	# StopIteration error 超出迭代器范围
# print(res)
(2) for 获取迭代器中的元素
it = map(int,lst)
for i in it:	# 用for循环一个一个获取并操作
	print(i)
(3) for + next 获取迭代器中的元素
it = map(int,lst)
for i in range(2):		# 用循环控制next只获取两次
	print( next(it) )
(4) list 强转迭代器 ,返回一个列表
it = map(int,lst)
lst = list(it)		# 直接将迭代器强转为列表
print(lst)

案例二:将列表[1,2,3,4]转化为[1,4,9,16]

对应列表里每个数的平方
常规写法:

lst = [1,2,3,4]
lst_new = []
for i in lst:		# 月薪2000的写法
	res = i ** 2
	lst_new.append(res)
print(lst_new)
map 方法一
lst = [1,2,3,4]
def func(n):		# 定义了返回参数平方的函数func
	return n ** 2
it = list(map(func,lst))
'''
将lst里的值一个个给func输入,
并将返回值组成为一个迭代器,
再将迭代器强转为列表
'''
map 方法二
lst = [1,2,3,4]
it = list(map( lambda n : n ** 2 , lst ))	# 用匿名函数将方法一简化

案例二:将dic = {97:“a”,98:“b”,99:“c”}中,给你[“a”,“b”,“c”] => 对应返回 [97,98,99]

常规写法:

# 看看就行,月薪2000的写法
lst = ["a","b","c"]
dic = {97:"a",98:"b",99:"c"}

# 1.将字典的键值对进行翻转
dic_new = {}
for k,v in dic.items():
	# print(k,v)
	dic_new[v] = k

print(dic_new)		# dic = {"a":97,"b":98,"c":99}

# 2.去获取键所对应的值
lst_new = []
for i in lst:
	res = dic_new[i]
	# 插入到新的列表里
	lst_new.append(res) 
print(lst_new)		# [97, 98, 99]
map 方法一
lst = ["a","b","c"]
dic = {97:"a",98:"b",99:"c"}
def func(n):		# 定义函数:反转字典键值对,并在输入键时返回值
	dic_new = {}
	for k,v in dic.items():
		dic_new[v] = k
	return dic_new[n]

it = map(func,lst)
print(list(it))		# [97, 98, 99]
map 方法二
lst = ["a","b","c"]
dic = {97:"a",98:"b",99:"c"}
def func(n):					# 定义函数func
	for k,v in dic.items():		# 将键值对打包成一个个元组并用k,v遍历
		if n == v:				# 当输入的参数等于元组中的v时
			return k			# 返回元组中的k
it = map(func,lst)
print(list(it))		# [97, 98, 99]

map可以接收多个iter,对应的func也要能接收相应数量的参数

lst1 = ['a','b','c','d','e','f']
lst2 = [1,2,3,4,5,6]
print(dict(map(lambda x,y:[x,y], lst1, lst2)))  # {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}

【filter】

功能:

  • 在自定义的函数中,过滤数据,
    如果返回True 代表保留数据,
    如果返回False 代表舍弃该数据,
    保留的数据存为迭代器,返回迭代器。

格式:filter(func,iterable)
参数:

  • func 自定义函数
    iterable 可迭代性数据(容器类型数据 range对象 迭代器)

返回值:

  • 迭代器

案例一:[1,2,3,4,5,6,7,8] => 只保留所有的奇数

常规写法:

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)
filter 改写
def func(n):
	if n % 2 == 0:
		return False
	else:
		return True
		
it = filter(func,lst)
print(list(it))
改写成lambda 表达式
lst = [1,2,3,4,5,6,7,8]
print("<===>")
it = filter(lambda n : True  if n % 2 == 1 else False , lst)
print(list(it))

【reduce】

功能:

  • 一次性从iterable当中拿出2个值,扔到func函数中进行处理,
    把运算的结果在和iterable的第三个值继续扔到func中做运算
    … 以此类推,最后输出累加的数据。

引入模块:rom functools import reduce

格式:reduce(func,iterable)

参数:

  • func 自定义函数
    iterable 可迭代性数据(容器类型数据 range对象 迭代器)

返回值:

  • 最后计算的结果

案例一:将[5,4,8,8] 转化为 5488

常规方法一:

lst = [5,4,8,8]
strvar = ""
for i in lst:			# 将lst每个元素强转为字符串
	strvar += str(i)	# 并将每个字符串拼接成一个字符串
intvar = int(strvar)	# 将结果的字符串强转为整形得到结果
print( intvar)			# 5488

常规方法二:

it = iter(lst)		# 将字符串强转为迭代器
num1 = next(it)
num2 = next(it)		# 用next获取迭代器的前两个值

total = num1 * 10 + num2	# 定义total的初始值

for i in it:
	total = total * 10 + i	# 循环叠加这个算法便能得到结果
print(total)	# 5488

"""
算法解析:
5 * 10 + 4 => 54
54 * 10 + 8 => 548
548 * 10 + 8 => 5488
"""
reduce 进行改写
from functools import reduce
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)  )

案例二:将"789" 转化为 789 (禁止使用int)

def func(x,y):		# 将两个数拼接成一个数的函数
	return x*10 + y
	
# 定义函数func:通过参数作为键,输出字典对应的值来转换一个字符
def func_int(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(func_int,"789")	# 用map将字符串每个字符转化为整形
res = reduce(func,it)		# 用reduce将所有数字拼接成一个数
print(res)		# 789

【sorted】

格式:sorted(iterable,reverse=False,key=函数)

功能: 排序

参数:

  • iterable 可迭代性数据(容器类型数据 range对象 迭代器)
    reverse 代表是否倒序 reverse=True 代表倒序 从大到小 reverse = False 代表正序,从小到大

key:自定义函数 或 内置函数

返回值:

  • 排序后的列表

(1) 默认从小到大排序 : 返回新的列表

# 排序列表
container = [100,200,13,-6,0]
# 排序元组
container = (100,200,13,-6,0)
# 排序集合
container = {100,200,13,-6,0}
# 字符串(按照ascii编码排序)
container = "oneal"
# 字典 (默认排序的是键)
container = {"a":1,"b":2,"c":3}

lst_new = sorted(container)
print(lst_new)

(2) 从大到小排序

lst_new = sorted(container,reverse=True)
print(lst_new)

(3) 通过内置函数排序

  • 按照绝对值排序 abs
print( abs(-200) )
lst = [-200,-300,9,20]
res = sorted(lst,key=abs)
print(res)		# [9, 20, -200, -300]

# 按照abs绝对值的大小进行排序]
"""
9 => abs(9) => 9
20 => abs(20) => 20
-200 => abs(-200) => 200
-300 => abs(-300) => 300
"""

(4) 通过自定义函数进行排序

lst = [19,27,35,48]
def func(n):
	return n % 10	# 取余的函数
# 按取余后的大小排序
res = sorted(lst,key = func)
res = sorted(lst,key = lambda n : n % 10)
print(res)		# [35,27,48,19]
"""
35 % 10 => 5
27 % 10 => 7
48 % 10 => 8
19 % 10 => 9
"""

对比sort与sorted:

sort 基于原有的列表进行排序,只限定列表类型
sorted 所有的容器类型数据都能排,返回一个全新的列表 (推荐)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值