可迭代对象&迭代器对象&for循环本质


1. 常用内置函数

"""
其中几个方法得到的结果类型是迭代器对象的类型,
所以想要打印出内容,必须用for循环或者其他容器类型包裹,如下例子:
res = zip(l1,name_list)
print(list(res))

res1 = zip(l1,name_list,l2,l3)
for i in res1:
	print(i)
"""

# 1. map()  # 映射
l = [1,22,333]
print(list(map(lambda x: x+1, l)))
# 循环获取列表中每个元素并传递给匿名函数保存返回值
# map方法详细介绍地址 
# 在这里:https://www.cnblogs.com/Joshua-jiaxue/p/15573256.html#_label4

# 2.zip()  拉链
l1 = [1,2,3,4]
name_list = ['jason','jack','joshua','jerry']
l2 = [33,52,53,56,3,2,67]
l3 = [234,435,56,345,763,33]
# 要求将索引相同的元素配对
res = zip(l1,name_list)
print(list(res))

res1 = zip(l1,name_list,l2,l3)
for i in res1:
	print(i)


# 3.max(),min()
l4 = [13,21,36,42,58,79,60,3,22]
print(max(l4))  # 79
print(min(l4))  # 3

dic = {
	'jason': 2000,
	'jack': 4000,
	'joshua':1000,
	'jerry':3000
}
# 想要获取工资最高的人
print(max(dic))  # joshua
# 由于根据key的字母ASCII的大小排序,所以得不到正确的结果。
# max还支持传入函数
print(max(dic, key=lambda x:dic[x]))  # jack


# 4.filter  # 过滤
l5 = [12,23,34,45,67,88]
res2 = filter(lambda x: x > 40, l5)
print(list(res2))


# 5.reduce  归总
# 将多个元素变成单个元素
from functools import reduce
l6 = [12,14,22,43,56,66,88,99]
res3 = reduce(lambda x,y: x+y, l6)
print(res3)  # 400

res4 = reduce(lambda a,b: a+b, l6, 50)
# 还可以额外添加值
print(res4)  # 450


2. 可迭代对象

  1. 什么叫迭代:
    1. 即更新换代,每次的更新都必须依赖于上一次的结果
    2. 主要用于取值。
    3. 迭代给我们提供了一种,不依赖于索引取值的方式。
  2. 可迭代对象
    1. 内置有__iter__方法的,都称之为可迭代对象
    2. 针对双下划线开头,双下划线结尾的方法,最为专业标准的读法为:“双下方法名”,“双下iter”。
    3. 内置的意思是可以通过.方法查看的。
    i = 12
    f = 1.12
    s = 'jack'
    l = [1,2,23,4]
    d = {'name':'jack','age':18}
    t = (1,2,3)
    se = {11,22,33,44}
    b = True
    file = open(r'a.txt','w',encoding='utf8')
    
    我们可以测试下哪些有__iter__方法。
    """
    含有__iter__的有
    	字符串,列表,字典,元组,集合,文件对象
    所以上述都可以称为可迭代对象。
    """
    print(d.__iter__())  # 类似于d.get()
    print(iter(d))  # 结果与上面一致
    print(d.__len__())
    print(len(d))
    """
    可迭代对象调用了__iter__方法后,会变成迭代器对象。
    且
    __iter__在调用的时候简便写法iter()
    一般情况下所有的双下方法都有一个简写:方法名()加括号。
    """
    

3. 迭代器对象

  1. 迭代器对象
    既含有__iter__方法,又含有__next__方法
  2. 如何生成迭代器对象
    将可迭代对象执行__iter__方法
  3. 文件对象本身既是可迭代对象,又是迭代器对象
  4. 迭代器对象无论执行了多少次__iter__方法,结果还是迭代器对象(本身)
i = 12  # 全没有
f = 1.12  #全没有
s = 'jack'  # 有iter
l = [1,2,23,4]  # 有iter
d = {'name':'jack','age':18}  # 有iter
t = (1,2,3)  # 有iter
se = {11,22,33,44}  # 有iter
b = True  #全没有
file = open(r'a.txt','w',encoding='utf8')  # 同时有iter和next

res = s.__iter__()
# 此时res有了__next__方法
# print(res.__next__())  # j

# 迭代器对象执行__next__方法其实就是在迭代取值(for循环)
# print(res.__next__())  # j
# print(res.__next__())  # a
# print(res.__next__())  # s
# print(res.__next__())  # o
# print(res.__next__())  # n
# print(res.__next__())  # 再取报错stopiteration

"""易错点!!!!!!"""
print(d.__iter__().__next__())  # username
print(d.__iter__().__next__())  # username
print(d.__iter__().__next__())  # username
print(d.__iter__().__next__())  # username
print(d.__iter__().__next__())  # username
# 每次得到的结果都是username,而不会报错

4. for循环的本质

4.1 for循环内部原理

l1 = [1,2,3,4,5,6,7,8,9,10,11,22,33,44,55,66]
# 循环打印出列表中每个元素,但是不能使用for循环

# 1.先将列表转为迭代器对象
res = l1.__iter__()

while True:
	print(next(res))
# 取完值后会报错:StopIteration

"""
for循环内部原理
	1.将关键字in后面的数据先调用__iter__方法,转为迭代器对象。
	2.循环执行__next__方法
	3.取完值后__next__会报错,但是,
	for循环会自动捕获该错误,并处理。

res = 数据.__iter__()
while True:
	监测代码是否报错
	res.__next__()
	如果报错则自动处理掉并结束while循环

"""


# 方法一:
# 统计次数,列表元素被打印完毕就停止循环
count = 0

num = len(l1)
while count < num:
    print(next(res))
    count += 1


"""重点在这里"""
# 方法二:
	异常捕获,如下

4.2 异常捕获

  1. 什么是异常??
    代码运行出错,会导致异常,异常发生后,如果没有解决方法,则会导致整个程序结束。

  2. 异常的三个重要组成部分:

    1. 异常的追踪信息traceback
      翻到错误的最下面,从下往上第一个蓝色字体鼠标左键点击,即可跳转到错误代码所在行。
    2. 异常的类型
      xxxxError
    3. 异常的原因
      异常的类型冒号后面的内容。
      错误的详细原因很重要。
      看完之后可能找到解决的方法。
  3. 错误的种类

    1. 语法错误
      不被允许的,出现了就立刻修改!!
    2. 逻辑错误
      可以被允许,出现之后尽快修改即可
      修改逻辑错误的过程,其实就是在从头到尾清理思路的过程。
      NameError
      IndexError
      KeyError
      ValueError
      ...等等
  4. 捕获异常的基本语法结构

try:
	有可能出现错误的代码
except 错误类型 as e:
	出错之后对应的处理机制(e是错误的详细信息)
except 错误类型 as e:
	出错之后对应的处理机制
except 错误类型 as e:
	出错之后对应的处理机制


try:
	print(name)
except NameError as e:
	print('变量名不存在', e)
	# as e 可加可不加,看自己需求。
# 变量名不存在 name 'name' is not defined


# 在我们不知道可能出现的错误类型的时候
# 有万能异常
try:
	int('abc')
except Exception:  # BaseException
	print('啥错都能解决。。。')

"""
异常捕获句式和万能异常
	1.有可能会出现错误的代码才需要被监测
	2.被监测的代码一定要越少越好
	3.异常捕获使用频率越低越好
	爬虫程序中会经常用到。
"""

# 下面我们来解决上面的问题
l1 = [1,2,3,4,5,6,7,8,9,10,11,22,33,44,55,66]
# 循环打印出列表中每个元素,但是不能使用for循环

# 1.先将列表转为迭代器对象
res = l1.__iter__()

while True:
	try:
		print(next(res))
	except StopIteration:
		print('打印完毕')
		break