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) 如何判断一个迭代器
- 如果内置成员中 含有 iter 和 next 两个方法,就可以判断是一个迭代器
我们拿上面代码块的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 所有的容器类型数据都能排,返回一个全新的列表 (推荐)