一、可迭代对象、迭代器
1、可以被for循环的数据类型(可迭代对象):
字符串(str)、列表(list)、字典(dict)、元祖(tuple)、range()
2、迭代器
2.1 将可迭代对象==>迭代器(__iter__())
st = 'abc' # 可迭代对象 st_iter = st.__iter__() # 迭代器 print(st_iter) # 返回 :<str_iterator object at 0x00000117E93A2F98>
2.2 将可迭代对象==>迭代器(iter(可迭代对象))
st = 'abc' st_iter = iter(st) print(st_iter)
# 返回 :<str_iterator object at 0x00000117E93A2F98>
2.3 迭代器取值(__next__())
# 1、调用函数内的方法去取值
st = 'abc' st_iter = st.__iter__() print(st_iter.__next__()) # 迭代器每次只取一次数据,取完一次后指针停留在当前位置,便于下次接着取值 print(st_iter.__next__()) print(st_iter.__next__()) # 返回: a b c
2.4 迭代器取值(next(迭代器))
2、调用函数去取值
st = 'abc' st_iter = st.__iter__() print(next(st_iter)) print(next(st_iter)) print(next(st_iter))
# 返回:
a
b
c
3、可迭代对象与迭代器的区别:
1) 可迭代对象可以转换成迭代器,迭代器不能逆转; 2)可迭代对象的方法:__iter__()
迭代器的方法:__iter__()、__next__()
4、判断 可迭代对象(Iterable) 和 迭代器(Iterator) 的两种方法:
4.1 方法一:
判断对象是否有"__iter__"方法
如果有,返回True,是可迭代对象
st = 'abc' print("__iter__" in dir(st)) # dir(o):显示所有的方法
返回:
True
4.2 方法二:
用isinstance()方法判断:
from collections import Iterable from collections import Iterator
# 判断是否为可迭代对象,返回True print(isinstance(st,Iterable))
# 判断是否为迭代器,返回True print(isinstance(st.__iter__(),Iterator)) 控制台报错: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working # 注:有报错没关系,是因为版本的原因(3.7.3)
5、迭代器的意义:
-
节省内存
-
迭代器有惰性机制(每次只取一次数据)
-
不能反复,一直往下执行(如:有100条数据,第一次循环,执行5条数据,第二次循环,从第6条开始执行)
6、for循环的机制(for循环会自动生成迭代器)
-
for循环中内部含有__iter__方法会自动将可迭代对象转换成迭代器;
-
再调用__next__方法
-
有异常处理机制(打印next方法,会一直循环可迭代对象,当循环结束,打印next方法就会报错,所以报错的时候加上异常处理)
7、用迭代器实现for循环
list = [1,2,3,4] # 1、先判断list是否是可迭代对象 if '__iter__' in dir(list): # 2、转化成迭代器 list_iter = list.__iter__() # 3、将迭代器里面的值依次取出并打印 while True: try: print(list_iter.__next__()) except StopIteration as e: print("--- 打印完毕!---%s"%e) break else: print("不是可迭代对象")
二、生成器
生成器的本质就是迭代器(所以自带__iter__() 和 __next__() 方法)
1、迭代器构建的三种方式:
- 可以用生成器函数
- 可以用各种推导式构建函数
- 可以通过数据转换
2、生成器函数(yield=>函数返回值)
def gener(): print(111) yield 'aaa' print(222) yield 'bbb' print(333) g = gener() print(g) # 打印生成器函数 print(g.__next__()) # 打印第一个返回值 print(g.__next__()) # 打印第二个返回值
返回:
<generator object gener at 0x000001EF1CDF0570>
111
aaa
222
bbb
3、return 和 yield 的区别
1) return : 返回值给调用者,并结束此函数 2)yield : 返回值给调用者,并将指针停留在当前位置
4、send
def gener(): print(111) yield "aaa" print(222) ret = yield ("bbb") print("----->",ret) print(333) yield "ccc" print(444) g = gener() print(g) print(g.__next__()) print(g.send(None)) print(g.send("BBB")) ## 给上一个 yield 赋值
返回:
<generator object gener at 0x000002BE42060570>
111
aaa
222
bbb
-----> BBB
333
ccc
5、send 与 __next__ 的区别
相同点:都是取迭代器里面的值 不同点: 1)send是给上一个yield赋值 2)send不能给第一个、最后一个yield赋值
三、列表推导式
1、列表推导式语法:
# 1.1 循环模式
l1 = [变量(或者加工后的变量) for 变量 in 可迭代数据类型] print(l1)
# 1.2 筛选模式
l1 = [变量(或者加工后的变量) for 变量 in 可迭代数据类型 if 条件] print(l1)
2、生成器表达式语法(小括弧啊里面有类型列表推导式的都是生成器)
l2 = (变量(或者加工后的变量) for 变量 in 可迭代数据类型) # 打印生成器 print(l2) # 取值 for i in l2: print(i)
3、实例
3.1 列表推导式
例一:30以内所有能被3整除的数
st = [i for i in range(31) if i % 3 ==0] print(st)
例二:30以内所有能被3整除的数的平方
st = [i*i for i in range(31) if i % 3 ==0] print(st)
例三:找到嵌套列表中名字含有两个“e”的所在名字
names = [['Tom','Billy','Jefferson','Andrew','Weseiy','Steven','Joe'], ['Alince','Jill','Ana','Wendy','Jennifer','sherry','Eva']] ee_name = [ j for i in names for j in i if j.count('e') == 2 ] print(ee_name)
3.2 字典推导式
例一:将一个字典的key和value对调
dict = {'a':1,'b':2} new_dict = {dict[k]:k for k in dict} print(new_dict)
例二:合并大小写对应的value值,将k统一成小写
dict = {'a':10,'b':34,'A':7,'z':3} new_dict = {k.lower():dict.get(k.lower(),0)+dict.get(k.upper(),0)for k in dict.keys()} print(new_dict)
3.3 集合推导式
例一:计算列表中每个值得平方,自带去重功能
set = {i**2 for i in [1,-1,2]} print(set)