iterable、iterator和iter()

iterable

能够一次返回一个成员的对象,iterable包括:所有的sequence序列类型(如:list,str,tuple),一些非序列类型如:(dict,file object和使用 iter() 方法或使用实现 Sequence 语义的 getitem() 方法定义的任何类的对象。)

sequence:通过__getitem__()特殊方法支持使用整数索引访问的可迭代对象iterable,并定义了返回序列长度的__len__()方法。iterable实现了__getitem__()方法和__len__()方法就变为了sequence,对于list,str,tuple都是序列类型。dict虽然也支持这两个方法,但是它不是只支持使用整数索引访问,而是支持immutable keys(不可变的keys)访问,所以它是mapping类型而不是sequence类型。

immutable :不可变对象,包括数字、字符串和元组。这样的对象不能改变。如果必须存储不同的值,则必须创建一个新对象。它们在需要常量哈希值的地方发挥重要作用,例如作为字典中的键。

iterable可以用在for循环中和许多其他需要序列的地方(zip(), map(),…)。当可迭代对象作为参数传递给内置函数 iter() 时,它会返回该对象的迭代器。

使用可迭代对象时,通常不需要调用 iter() 或自己处理迭代器对象,for 语句会自动为您执行此操作,创建一个临时未命名变量以在循环期间保存迭代器。即我们再用for语句访问iterable时,实际上内部已经将其调用iter()方法转为迭代器,然后依次访问。

iterator

iterator是表示数据流的对象,重复调用iterator的 next() 方法(或将其传递给内置函数 next())会返回流中的连续对象。当没有更多数据可用时,会引发 StopIteration 异常。

迭代器需要有一个返回迭代器对象本身的 iter() 方法,所以每个迭代器也是可迭代的,并且可以在大多数接受其他可迭代对象iterable的地方使用。一个值得注意的例外是尝试多次迭代的代码。每次将容器对象(例如列表)传递给 iter() 函数或在 for 循环中使用它时,都会生成一个全新的迭代器。使用迭代器尝试这样做只会返回与前一次迭代中使用的相同的迭代器对象,在原来的基础上接着迭代。

data = [("p", 1), ("p", 2), ("p", 3),
        ("h", 1), ("h", 2), ("h", 3)]

a = iter(data)  # 将list(iterable)作为iter的参数,每次会生成新的迭代器iterator
print(next(a))
b = iter(data)
print(next(b))
c = iter(b)  # 将迭代器(iterator)作为iter的参数,不会生成新的迭代器,而是返回传入的迭代器,下次迭代会在该迭代器的基础上接着往后迭代
print(next(c))

在这里插入图片描述

iter()

iter() 函数用来生成迭代器,返回值为一个迭代器对象。

iter(object[, sentinel])

参数:

  • object:如果没有传入sentinel参数,则object为支持迭代器协议(实现_iter_()方法的),或者是支持序列协议(实现_getitem_()方法)且是从0开始索引的collection集合对象。
  • sentinel:sentinel 参数是可选的,直译过来是哨兵的意思。如果传递了第二个参数,则参数 object 必须是一个可调用的对象(如,函数),此时,iter 创建了一个迭代器对象,每次调用这个迭代器对象的__next__()方法时,都会调用 object,当可调用对象的返回值等于 sentinel 的值时,抛出 StopIteration 的异常,否则返回可调用对象的当前值。

collection:sized iterable container 大小可迭代的容器container类, collection继承container,并实现了__iter__, __len__方法,包括:序列类型,set,mapping等,dict, list, set, and tuple这些都是collection类型,collections模块扩展了更多的collection类型。
container: 提供了 contains()方法的类。包括:序列类型,set,mapping,KeysView,ItemsView等等。

举例说明一下:
常见的,只传入collection类型的数据:

In [5]: iter("123")
Out[5]: <str_iterator at 0x105c9b9e8>
In [6]: iter([1, 2, 3])
Out[6]: <list_iterator at 0x105f9f8d0>

传入sentinel参数:
该场景是创建一个 blokc-reader,即根据条件中断读取。比如:从二进制数据库文件读取固定宽度的块,直到到达文件的末尾,代码示例如下:

from functools import partial
with open('mydata.db', 'rb') as f:
	# 中断条件为读到b''
    for block in iter(partial(f.read, 64), b''):
        process_block(block)

该部分参考:https://zhuanlan.zhihu.com/p/69496512https://docs.python.org/3/library/functions.html?highlight=iter#iter

总结:

  • iterable是可迭代对象,iterator是迭代器,iter()方法是生成迭代器的方法,iter()方法可以将iterable变为iterator。

  • 直接作用于for循环的对象统称为可迭代对象:Iterable。可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator

  • 生成器是表示数据流的对象,不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration。

  • list、dict、str虽然是Iterable,却不是Iterator,这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的

更多参考:
https://www.liaoxuefeng.com/wiki/1016959663602400/1017318207388128
https://www.liaoxuefeng.com/wiki/1016959663602400/1017316949097888
https://docs.python.org/3/library/functions.html?highlight=iter#iter

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱学习的贝塔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值