迭代和可迭代

什么是迭代(iteration)?
如果给定一个list或tuple,我们要想访问其中的某个元素,我们可以通过下标来,如果我们想要访问所有的元素,那我们可以用for循环来遍历这个list或者tuple,而这种遍历我们就叫做迭代。

可迭代(iterable)?

其实你已经知道,不是所有的数据类型都是可迭代的。那么可迭代的数据类型都有什么特点呢?

print(dir([1,2]))
print(dir((2,3)))
print(dir({1:2}))
print(dir({1,2}))
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']
['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update']
结果

总结一下我们现在所知道的:可以被for循环的都是可迭代的,要想可迭代,内部必须有一个__iter__方法。迭代器协议

from collections import Iterable

l = [1,2,3,4]
t = (1,2,3,4)
d = {1:2,3:4}
s = {1,2,3,4}

print(isinstance(l,Iterable))
print('__iter__' in dir([l]))
print(isinstance(t,Iterable))
print('__iter__' in dir([t]))
print(isinstance(d,Iterable))
print('__iter__' in dir([d]))
print(isinstance(s,Iterable))
print('__iter__' in dir([s]))
判断是否可迭代

接着分析,__iter__方法做了什么事情呢?

print([1,2].__iter__())

结果
<list_iterator object at 0x1024784a8>

执行了list([1,2])的__iter__方法,我们好像得到了一个list_iterator,现在我们又得到了一个新名词——iterator。

周末班:Python基础之函数进阶

iterator,这里给我们标出来了,是一个计算机中的专属名词,叫做迭代器。

迭代器

我们调用可迭代对象的__iter__方法之后,得到了一个新东西--迭代器。

那迭代器是什么呢?请继续往后阅读吧。

迭代器协议

既什么叫“可迭代”之后,又一个历史新难题,什么叫“迭代器”?

虽然我们不知道什么叫迭代器,但是我们现在已经有一个迭代器了,这个迭代器是一个列表的迭代器。

我们来看看这个列表的迭代器比起列表来说实现了哪些新方法,这样就能揭开迭代器的神秘面纱了吧?

'''
dir([1,2].__iter__())是列表迭代器中实现的所有方法,dir([1,2])是列表中实现的所有方法,都是以列表的形式返回给我们的,为了看的更清楚,我们分别把他们转换成集合,
然后取差集。
''' #print(dir([1,2].__iter__())) #print(dir([1,2])) print(set(dir([1,2].__iter__()))-set(dir([1,2]))) 结果: {'__length_hint__', '__next__', '__setstate__'}

我们看到在列表迭代器中多了三个方法,那么这三个方法都分别做了什么事呢?

iter_l = [1,2,3,4,5,6].__iter__()
#获取迭代器中元素的长度
print(iter_l.__length_hint__())
#根据索引值指定从哪里开始迭代
print('*',iter_l.__setstate__(4))
#一个一个的取值
print('**',iter_l.__next__())
print('***',iter_l.__next__())

这三个方法中,能让我们一个一个取值的神奇方法是谁?

没错!就是__next__

在for循环中,就是在内部调用了__next__方法才能取到一个一个的值。

那接下来我们就用迭代器的next方法来写一个不依赖for的遍历。

l = [1,2,3,4]
l_iter = l.__iter__()
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)

这是一段会报错的代码,如果我们一直取next取到迭代器里已经没有元素了,就会抛出一个异常StopIteration,告诉我们,列表中已经没有有效的元素了。

这个时候,我们就要使用异常处理机制来把这个异常处理掉。

l = [1,2,3,4]
l_iter = l.__iter__()
while True:
    try:
        item = l_iter.__next__()
        print(item)
    except StopIteration:
        break

那现在我们就使用while循环实现了原本for循环做的事情,我们是从谁那儿获取一个一个的值呀?是不是就是l_iter?好了,这个l_iter就是一个迭代器。

迭代器遵循 迭代器协议 :必须拥有__iter__方法和__next__方法。

还账:next和iter方法

相关文章:

  • 2022-12-23
  • 2021-07-17
  • 2022-01-03
  • 2022-02-09
  • 2021-05-19
  • 2021-08-12
  • 2021-06-09
  • 2021-06-06
猜你喜欢
  • 2021-08-29
  • 2021-06-12
  • 2021-09-10
  • 2021-08-29
  • 2021-07-24
  • 2021-05-18
  • 2021-12-05
相关资源
相似解决方案