目录
今日总结
一、迭代器
1. 什么是迭代器(iter)
是序列
迭代器作为序列无法获取元素的个数,打印迭代器的时候也无法查看所有的元素
如果要获取元素的值必须将元素从迭代器中取出来,而且某个元素如果取出来了就无法再放回迭代器中(取一个少一个)
2. 创建迭代器
- 将其他序列转化成迭代器 - 所有序列都可以转换成迭代器
- 创建生成器
iter1 = iter('abc')
print(iter1) # <str_iterator object at 0x00000000025178B0>
# print(len(iter1)) # 报错!TypeError: object of type 'str_iterator' has no len()
iter2 = iter([100, 'abc', True, [1, 2]])
print(iter2) # <list_iterator object at 0x0000000001E26FD0>
iter3 = iter({10, 20, 30})
print(iter3) # <set_iterator object at 0x000000000256B040>
3. 获取元素
不管以什么样的方式获取到了迭代器的元素,那么这个元素就会从迭代器中消失
-
next(迭代器) - 返回指定迭代器最前面的元素
-
遍历
iter4 = iter('python')
print(next(iter4)) # p
print(next(iter4)) # y
print(next(iter4)) # t
print(next(iter4)) # h
print(next(iter4)) # o
print(next(iter4)) # n
# print(next(iter4)) # 取一个空的迭代器会报错!StopIteration
iter5 = iter([10, 20, 'abc', True])
for x in iter5:
print('x', x)
# print(next(iter5)) # 报错!StopIteration
iter6 = iter('abc')
list1 = list(iter6)
print(list1)
# print(next(iter6)) #报错!StopIteration
二、生成器
1. 什么是生成器
是序列
获取元素的方式和迭代器一样。一个数据只能取一次,取一个少一个,无法查看到所有数据
2. 怎么创建生成器
调用带有yield关键字的函数就可以得到一个生成对象
# 调用没有yield的函数:会执行函数体并且获取函数返回值
def func1():
print('========')
print('++++++++')
result = func1()
print(result)
print('-----------------------')
# 调用带有yield关键字的函数:不会执行函数体,返回的数据是一个生成器对象
def func2():
print('========')
print('++++++++')
if False:
yield
return 100
result = func2()
print(result) # <generator object func2 at 0x00000000020562E0>
print(list(result)) # [] -> 生成器result产生数据个数是0
3. 确定生成器产生数据的能力(包括产生数据的个数和值)
确定个数:执行完生成器对应的函数,会遇到几次yield,这个生成器就会产生多少个数据
def func3():
yield 100
yield 'abc'
yield False
# for _ in range(3):
# yield
g1 = func3()
# next(g1)
# next(g1)
# next(g1)
# next(g1) # 报错!StopIteration
print(list(g1)) # [100, 'abc', False]
4. 生成器产生数据的原理
在获取数据的时候才去执行函数体,而且每次执行到yield就停下来,将yield后面值作为获取到的数据,同时记录结束位置,下一次获取元素接着上次结束的位置往后执行
def func4():
print('开始')
yield 10
print('-------')
yield 100
print('+++++++')
yield 1000
print('结束')
g2 = func4()
# print('result1:', next(g2))
# print('result2:', next(g2))
# print('result2:', next(g2))
# print('result2:', next(g2)) # 会打印完'结束'后报错!StopIteration
def func5():
print('hello')
yield 11
print('world')
yield 22
g3 = func5()
next(g2) # 开始
next(g3) # hello
next(g2) # -------
next(g3) # world
# 练习:创建一个学号生成器,能产生指定范围的学号,学号的格式是:XXXxxx
# create_id(前缀, 长度) -> 前缀是java, 长度是3 —> java001 ~ java999
# -> python2102, 长度是4 -> python21020001 ~ python21029999
def create_id(pre: str, length: int):
for x in range(1, 10**length):
yield f'{pre}{x:0>{length}}'
c1 = create_id('py', 4)
for x in c1:
print(x)
四、生成器的优点
只读指令的数据,不占用运行内存,效率高
import csv
# 非生成器写法,需要遍历整个文件
def read_file1():
with open('abc.csv', encoding='utf-8', newline='') as f:
reader = csv.reader(f)
result = []
for x in reader:
result.append(x)
return result
# s = read_file1()
# print(s)
# 生成器写法,只读指令数据,无需遍历整个文件
def read_file2():
with open('abc.csv', encoding='utf-8', newline='') as f:
reader = csv.reader(f)
# result = []
for x in reader:
yield x