1. 迭代器
迭代器:他不是函数,只是一个称呼。
python中一切皆是对象(数据类型)
可迭代对象:含有 .__ iter __方法的数据类型就叫做可迭代对象。
除了数字类型,所有数据类型都是可迭代对象。可迭代的对象:Python内置str、list、tuple、dict、set、file都是可迭代对象。
特点:
- 内置有
__iter__
方法的都叫可迭代的对象。
x = 10 #则不是可迭代对象 可迭代对象位 .__iter__ s = "adc" s.__iter__ lt = [1,2,3] lt.__iter__ tup = (1,) tup.__iter__() se = {1} se.__iter__() dic ={"a":1} dic.__iter__() fw = open("text","a+",encoding="utf-8") fw.seek(0,0) fw.__iter__() # 除了数字类型,所有数据类型都是可迭代对象
迭代器对象
迭代器对象:含有 .__ iter __ 和 .__ next __方法的对象就是迭代器对象。
概念:可迭代的对象执行__iter__
方法得到的返回值。并且可迭代对象会有一个__next__
方法。
只有字符串和列表都是依赖索引取值的,而其他的可迭代对象都是无法依赖索引取值的。因此我们得找到一个方法能让其他的可迭代对象不依赖索引取值。
s = "adc" s_iter = s.__iter__() print(s_iter.__iter__()) #不依赖索引取值 print(s[0]) #索引取值 print(s_iter.__iter__()) print(s[1]) print(s_iter.__iter__()) print(s[2]) 为什么要有迭代器对象:提供了 不依赖索引取值的手段 dic = {'a': 1, 'b': 2, 'c': 3} dic_iter = dic.__iter__() print(dic_iter.__next__()) # 迭代取值 --》 基于上一个值 print(dic_iter.__next__()) print(dic_iter.__next__()) #取不到则报错
为什么要有迭代器对象:提供了 不依赖索引取值的 手段
dic = {'a': 1, 'b': 2, 'c': 3} dic_iter = dic.__iter__() print(dic_iter.__next__()) #a print(dic_iter.__next__()) #b print(dic_iter.__next__()) #c print(dic_iter.__next__()) #取不到则报错
对上面迭代问题,我们使用while循环精简 使用try: escept stopiteration:的异常处理模块
模板 dic_iter = dic.__iter__() while True: try: print(dic_iter.__next__()) except StopIteration: break 列题: s = 'hello' iter_s = s.__iter__() while True: try: print(iter_s.__next__()) except StopIteration: #除了迭代对象(hello)停止迭代运行 h e l l o break
总结
迭代器对象:执行可迭代对象的__iter__
方法,拿到的返回值就是迭代器对象。
特点:
- 内置
__next__
方法,执行该方法会拿到迭代器对象中的一个值 - 内置有
__iter__
方法,执行该方法会拿到迭代器本身 - 文件本身就是迭代器对象。
缺点:
- 取值麻烦,只能一个一个取,并且只能往后取,值取了就没了
- 无法使用len()方法获取长度
for循环原理
for循环原理:(for循环本质就是一个while循环,只不过是一个一定可控的while循环)
for循环称为迭代器循环,in后必须是可迭代的对象
list = [1,2,3,4] for i in liast: print(i) # 1,2,3,4
牢记:
可迭代对象: 含有__ iter __ 方法叫做可迭代对象 --> 除了数字类型都是可迭代对象 --> 可迭代对象使用 __ iter __变成迭代器
迭代器对象: 含有__ iter __ 和 __ next __ 方法叫做迭代器对象 --> 只有文件时迭代器对象 --> 迭代器使用 __ iter __依然是迭代 器
可迭代对象不一定是迭代器对象; 迭代器对象一定是可迭代对象
2.三元表达式
条件成立时的返回值 if 条件 else 条件不成立时的返回值
通常用: x = 10 y = 20 if x > y: print(x) else: print(y) #20 三元表达式: x = 10 y = 20 print(f"x if x > y else y: {x if x > y else y}") #x if x > y else y: 20
3.列表推存式
lt = [] for i in range(10): lt.append(i) lt = [i**2 for i in range(10)] print(lt) #[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
from typing import Iterable #导出一个可迭代对象类型。
print(isinstance(range(10),Iterable)) #判断是否属于该数据类型。
4.字典生成式
dic = {} for i in range(10): dic[i] = i print(dic) # 0:0 1:1...9:9 dic = {i:i**2 for i in range(10)} print(dic) # 0:0 1:1 2:4.....9:81
zip (解压缩)
res = zip([1,2,3],[4,5,3,2,2],"qwer") ## res是一个迭代器,__next__返回元组 print(res.__next__()) #(1, 4, 'q') print(res.__next__()) #(2, 5, 'w') print(res.__next__()) #(3, 3, 'e') print(res.__next__()) #报错 #则列表中的数取完,则报错。
lt1 = ["a","b","c"] lt2 = [1,2,3] dic = {k:v**2 for k,v in zip(lt1,lt2)} print(dic) #{'a': 1, 'b': 4, 'c': 9} lt = list("abc") print(lt) # ['a','b',"c"]
5.生成器生成式
generator 本质是一个迭代器 --> 生成器:本质就是迭代器,生成器就是一个自定义的迭代器。
# 生成器表达式: 看成老母鸡,节省内存空间,用就下蛋 g = (i for i in range(10000)) print(g) for i in g: print(i) # 列表推导式: 看成一筐鸡蛋,非常占用内存空间 lt = [i for i in range(10000)] print(lt)
6.生成器
generator 本质是一个迭代器 --> 生成器:本质就是迭代器,生成器就是一个自定义的迭代器。
生成器:含有yield关键字的函数叫生成器
def ge(): #1 #3 #6 yield 3 #7 #9 yield 4 #10 print(ge()) #2 ge()得到一个生成器 --> 生成器本质是迭代器 <str_iterator object at 0x00000293FE9BE148> 列print(s_iter.__iter__())。。。 g=ge() #4 得到一个生成器 print(g.__next__()) #5 print(g.__next__()) #8 print--> 3,4 #for i in g: # print(i) #简化上面两个打印值
6.1 特征
# yield的特性 # 1. 暂停函数 # 2. 通过next取值 # return的特性 # 1. 终止函数 # 2. 通过调用函数拿到值
迭代器套迭代器
ef sub_generator(): yield 1 yield 2 for i in range(3): yield i for i in sub_generator(): print(i) # 1 2 0 1 2
def range(start) count = 0 while count <start: yield count count += 1 for i in range(10) print(i)