FRI.迭代器
迭代器
什么是迭代器
- 迭代器是用来迭代取值的工具
- 迭代就是一个重复的过程,但是每次重复都是基于上一次的结果进行,类似于汽车中期改款
- 迭代器分为可迭代对象(Iterable Object)和迭代器对象(Iterator Object)
# 单纯的重复不叫迭代
while True:
1 + 1
# 初识迭代操作
count = 1
while count < 5:
print(count)
count += 1
- 优点
- 找到一种通用的迭代取值的方案
- 惰性计算,节省内存**(迭代器对象在未调用前,可以存放无穷个元素,也只占用代码空间,在调用__next__方法时才会逐个产生值)**
- 缺点
- 不能指定取值,只能依次取值
- 迭代器对象是一次性的,一个迭代器对象取值完毕,则不能继续取值
可迭代对象
- 一类是集合数据类型,如 list 、tuple 、dict 、set 、str、文件等
- 一类是生成器,包括生成器和带 yield 的各类生成式。
这些可以直接作用于 for 循环的对象统称为可迭代对象
1. 'aaa'
2. [1,2]
3. (1,2)
4. {'1': 2}
5. {1,2}
6. open('a.txt',mode='wt')
- 调用可迭代对象的
__iter__
会得到一个返回值,该返回值是迭代器对象
迭代器版本
1. 'aaa'.__iter__()
2. [1,2].__iter__()
3. (1,2).__iter__()
4. {'1': 2}.__iter__()
5. {1,2}.__iter__()
6. open('a.txt',mode='wt').__iter__()
# 可迭代对象通过__iter__()内置方法转变为迭代器版本,再通过__next__内置方法取值,但可迭代对象的迭代器版本 != 迭代器对象
- 补充:可以使用 isinstance() 判断一个对象是否是
__iter__
对象
迭代器对象特点
open('a.txt',mode='wt').__iter__()/__next__()
- 内置__next__方法
- 内置__iter__方法
- 返回其本身
- 为了简化 for 循环设计
- **迭代器对象(Iterator)一定是可迭代对象**
- **可迭代对象(Iterable)不一定是迭代器对象**
for 循环原理
list = [1, 2, 3, 4]
# 调用 in 后面那个对象的__iter__内置方法,得到一个迭代器对象 iter_list
iter_list = iter(list)
# i = next(iter_list),然后运行循环体代码
while True:
# 重复步骤 2,直到取完值,抛出异常,for 循环会自动捕捉异常并结束循环
try:
print(next(iter_list))
except StopIteration:
break
list = [1, 2, 3, 4]
# for 循环工作原理
# 调用 in 后面那个对象的__iter__内置方法,得到一个迭代器对象 iter_list
# i = next(iter_list),然后运行循环体代码
for i in list
# 重复步骤 2,直到取完值,抛出异常,for 循环会自动捕捉异常并结束循环
print(i)
生成器(Genrator Object) – 自定义迭代器
def func():
print('one')
yield 111
print('two')
yield 222
print('three')
yield 333
g = func()
res = next(g) # one
print(res) # 111
res = next(g) # two
print(res) # 222
res = next(g) # three
print(res) # 333
- 函数内但凡出现 yield 关键字,在调用函数不会立即执行函数体代码,而会返回一个生成器对象,生成器对象本质就是一个自定义的迭代器对象
yield 与 return
- 相同
- 均为返回值,都可以返回任意类型、个数的值
- 不同
- return 只能返回一次值,函数立即结束
- yield 可以返回多次值,yield 可以暂停函数的运行生成式
函数递归调用
什么是函数递归
- 函数递归是函数嵌套的特殊格式,即在调用一个函数时,在内部调用了其自己(重复相同逻辑)
递归分为两个阶段
- 回溯: 一层一层往下调用
- 递推:一层一层往上退出结果
为什么要用递归
l = [1,[2,[3,[4,[5,[6]]]]]]
def cycle(l):
for i in l:
if type(item) is not list:
print(item)
else:
cycle(item)
递归实现二分法
nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
def search(m, n):
print(n)
if len(n) == 0:
print("It's not exists")
mid = len(n) // 2
if n[mid] == m:
print("Got it")
elif n[mid] > m:
"""in the left"""
n = n[:mid]
search(m, n)
else:
"""in the right"""
n = n[mid + 1:]
search(m, n)
serach(7, nums)
三元表达式
- 条件成立时的返回值 + if + 条件 + else + 条件不成立时的返回值
res = 'ok' if 'a' == 'a' else 'no'
print(res)
生成式
列表生成式
-
list = [expression for item1 in iterable1 if condition1]
1. 不带条件的列表生成式
l = []
for i in range(10):
l.append(i)
l = ['ok' for i in range(10)]
2. 带条件的列表生成式
l = []
for i in range(10):
if i > 3:
l.append(i)
l = [i for i in range(10) if > 3]
字典生成式
dic = {'k%d' % i: i for i in range(10)}
print(dic)
# {'k0': 0, 'k1': 1, 'k2': 2, 'k3': 3, 'k4': 4, 'k5': 5, 'k6': 6, 'k7': 7, 'k8': 8, 'k9': 9}
集合生成式
dic = { i for i in range(10)}
# {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
生成器表达式
generator = (i for i in range(5))
print(gererator)
# <generator object <genexpr> at 0x10f296900>
"元组即不可变列表,可以通过 'tuple + 列表生成式'快速生成,故而将此方法作为生成器表达式 "