可迭代对象
对象内部含有 __iter__方法就是可迭代对象。
可迭代对象:str list dict tuple set range()
可迭代对象满足可迭代协议
判断一个对象是否可迭代:
第一个方法:
print('__iter__ in dir(s))
第二个方法:
from collections import Iterable # 判断可迭代对象 from collections import Iterator # 判断迭代器 print(isinstance('alex', Iterable)) # 判断类型
迭代器:
对象内部含有__iter__方法,且含有__next__方法就是迭代器。
判断一个对象是否迭代器:
print('__next__' in dir(f))
# 可迭代对象 # for i in 'abc': # # print(i) # 对象内部含有 __iter__ 方法就是可迭代对象。 # s = '123' # print(dir(s)) # 判断一个对象是否可迭代对象: # 第一种方法 # print('__iter__' in dir(s)) # 第二种方法 from collections import Iterable # 判断可迭代对象 from collections import Iterator # 判断迭代器 print(isinstance('alex', Iterable)) # 判断类型 # 迭代器 # 判断一个对象是否可迭代器 f = open('a', encoding='utf-8', mode='w') print('__next__' in dir(f))
可迭代对象 vs 迭代器
- 1. 可迭代对象不能取值,迭代器是可以取值的。
- 可迭代对象 --->(转化成) 迭代器:
- 2. 迭代器非常节省内存。
- 只加载一个内存地址,next一下,加载这个内存的地址+
- 3. 迭代器每次只会取一个值。
- 4. 迭代器单向的,不反复,一条路走到头。会记录地址
数据量很大 只是取值 用迭代器。
while循环 模拟 for 循环内部机制:
- 1. 将可迭代对象转化成迭代器。
- 2. 调用__next__ 方法取值
- 3. 利用异常处理停止报错
# 可迭代对象 --->(转化成) 迭代器: lis = [1, 2, 3] # 可迭代对象 ite1 = lis.__iter__() # 迭代器 print(ite1) # 迭代器如何取值 next一次,取一个值 print(ite1.__next__()) # 写一步 取一个 # while循环 模拟 for 循环: # 1. 将可迭代对象转化成迭代器。 # 2. 调用__next__ 方法取值 # 3. 利用异常处理停止报错 s = 'sdgs' iter2 = s.__iter__() while 1: try: print(iter2.__next__()) except StopIteration: break
生成器
生成器:就是自己python用代码写的迭代器,生成器的本质就是迭代器。
用一下两种方式构建一个生成器:
- 通过生成器函数
- 生成器表达式
def func2(x): x += 1 print(111) yield x print(222) g_obj = func2(5) # 生成器函数对象 # print(g_obj) <generator object func2 at 0x000001933AEB9408> # g_obj.__next__() #111 # g_obj.__next__() #222 # 一个next对应一个yield # yield 将值返回给 生成器对象.__next__()
yield return 区别
- return结束函数,给函数的执行者返回值
- yield 不会结束函数,一个next对应一个yield,给 生成器对象.__next__() 返回值
生成器函数 迭代器
- 区别区别1:自定制区别
- 区别2:内存级别的区别 迭代器需要可迭代对象进行转化。
可迭代对象是非常占内存的 生成器是直接创建,不需要转化。从本质上就节省内存。
区别1 自定制去呗 # l1 = [1, 2, 3, 4, 5] # l1.__iter__() # def func1(x): # x += 1 # yield x # x += 3 # yield x # x += 5 # yield x # # # g1 = func1(5) # print(g1.__next__()) # print(g1.__next__()) # print(g1.__next__()) # 区别2 内存级别区别 # def func3(): # for i in range(100000): # yield i # g2 = func3() # for i in range(50): # print(g2.__next__())

def func(x): x += 1 yield x x += 2 yield x # 得到两个生成器对象 # print(func(8).__next__()) # 9 # print(func(8).__next__()) # 9 # 得到一个生成器对象 g = func(8) print(g.__next__()) # 9 print(g.__next__()) # 11
send 与 next 区别
- send 与 next 一样,也是对生成器取值(执行一个yield)的方法
- send 可以给 上一个yield传值。
- 第一次取值永远都是next
- 最后一个yield永远也得不到send传的值
# send 与 next def func1(): # print(1) count = yield 6 print(count) # print(2) yield 7 # print(3) yield 8 g1 = func1() # next(g1) print(next(g1)) g1.send('alex') next(g1)
列表推导式:一行代码几乎搞定你需要的任何列表
-
循环模式 [变量(加工后的变量) for 变量 in iterable]
-
筛选模式 [变量(加工后的变量) for 变量 in iterable if 条件]

l = [i for i in range(1,101)] print(l) l = ['python %s 期' % i for i in range(1, 16)] print(l) l = [i**2 for i in range(1, 11)] print(l)

l = [i for i in range(1, 31) if i % 2 == 0] print(l) l = [i for i in range(1, 31) if i % 3 == 0] print(l) l = [i**2 for i in range(1, 31) if i % 3 == 0] print(l) names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'], ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']] l = [j for i in names for j in i if j.count('e') == 2] print(l)
列表推导式:
优点:一行解决,方便。
缺点:容易着迷,不易排错,不能超过三次循环
列表推导式不能解决所有列表的问题,所以平时的代码不要太刻意用。
# 生成器表达式: 将列表推导式的 [] 换成 () 即可 g = (i for i in range(100)) print(g.__next__()) print(next(g)) #