第 11 章 迭代器 vs 生成器

1. 迭代器

先区分两个概念:可迭代对象(iterable)、迭代器(iterator)

1️⃣可迭代对象(iterable)

概念:能被 for 循环遍历的对象,就是可迭代对象(iterable)

如下这些都是可迭代对象(iterable):

names = ['张三', '李四', '王五']
citys = ('北京', '上海', '深圳')
msg = 'hello'

for item in names:
    print(item)

如下这些不是可迭代对象(iterable):

age = 10
def test():
    pass

for item in test:
    print(item)
endregion

可迭代对象都拥有__iter__方法。

names = ['张三', '李四', '王五']
citys = ('北京', '上海', '深圳')
msg = 'hello'
age = 10
def test():
    pass

names.__iter__()
citys.__iter__()
msg.__iter__()

print(hasattr(names, '__iter__'))
print(hasattr(citys, '__iter__'))
print(hasattr(msg, '__iter__'))
print(hasattr(age, '__iter__'))
print(hasattr(test, '__iter__'))

2️⃣迭代器(iterator)

调用__iter__方法会得到:迭代器(iterator)

  • 备注1:__iter__是一个魔法方法,当调用iter函数时,__iter__会自动调用。
  • 备注2:可迭代对象.__iter__() 等价于: iter(可迭代对象)。
  • 备注3:如果iter(obj)能得到一个迭代器(iterator),那obj就是可迭代对象。
names = ['张三', '李四', '王五']
citys = ('北京', '上海', '深圳')
msg = 'hello'

print(names.__iter__())
print(citys.__iter__())
print(msg.__iter__())

print(iter(names))
print(iter(citys))
print(iter(msg))

迭代器(iterator)拥有__next__方法,每次调用都会根据当前的状态,返回下一个元素。

  • 备注1:迭代器.__next__() 等价于 next(迭代器)。
  • 备注2:当所有元素全都取出后,若继续调用__next__,Python会抛出StopIteration异常。
names = ['张三', '李四', '王五']
it = iter(names)
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())

print(next(it))
print(next(it))
print(next(it))
print(next(it))

编写for循环遍历names列表

names = ['张三', '李四', '王五']
for item in names:
    print(item)

for循环背后的逻辑

names = ['张三', '李四', '王五']
# 1️⃣调用【可迭代对象的__iter__方法】获取到一个迭代器(iterator)
it = iter(names)
# 2️⃣开启一个无限循环
while True:
    try:
        # 3️⃣调用__next__方法,获取下一个元素
        item = next(it)
        print(item)
    except StopIteration:
        # 4️⃣捕获 StopIteration 异常,随后结束循环
        break

迭代器(iterator)也拥有__iter__方法,并且其返回值是迭代器自身。

这么设计的原因:让 for 循环也能遍历迭代器(即:为了让 iter(迭代器) 不出错)。

names = ['张三', '李四', '王五']

it = iter(names)
print(it)

result = iter(it)
print(result)

x = iter(result)
print(x)

it = iter(names)
for item in it:
    print(item)

迭代器协议:一个对象如果同时满足如下规范,那该对象就是一个迭代器:

  1. 能被iter()接受。
  2. 能被next()一步一步取值。

迭代器是一次性的,状态只会向前推进,且不会自动重置(迭代器在遍历的过程中会被“消耗”)。

names = ['张三', '李四', '王五']
it1 = iter(names)
it2 = iter(names)

print(it1)
print(it2)

print(next(it1))
print(next(it1))
print(next(it1))
print(next(it1)) # 此行代码会抛出异常,因为此时迭代器已经被耗尽了

# 如想重新依次获取元素,需要使用新的迭代器it2
print(next(it2))
print(next(it2))
print(next(it2))
© 版权声明
THE END
喜欢就支持一下吧
点赞11 分享
评论 抢沙发
头像-大赛人网
欢迎您留下宝贵的见解!
提交
头像-大赛人网

昵称

取消
昵称

    请登录后查看评论内容