写点什么

python 小知识 -rethinking python 迭代器

作者:AIWeker
  • 2022 年 7 月 17 日
  • 本文字数:2046 字

    阅读完需:约 7 分钟

python小知识-rethinking python 迭代器

python 中的所有集合对象(如 str list dict set tuple)都是可迭代的对象,通过 iter()函数都可以变成一个迭代器。


  • 迭代器就是可以通过序列方式顺序访问可迭代对象中的元素

  • 实现了__iter____next__的对象就是一个迭代对象

1.如何判断可迭代对象和迭代器


from collections import Iterable, Iteratoralist = [1, 3, 4]print(isinstance(alist, Iterable)) # Trueprint(isinstance(alist, Iterator)) # Falseprint(isinstance(iter(alist), Iterator)) # True

print('__iter__' in dir(alist)) # Trueprint('__next__' in dir(alist)) # Falseprint('__next__' in dir(iter(alist))) True
复制代码


从上可知,可以通过Iterable来判断是否可迭代, 通过Iterator来判断是否是迭代器; 也可以通判断是否实现了__iter____next__来判断是否是迭代器和可迭代对象。


2.如何使用迭代器


iter_list = iter(alist)for i in iter_list:    print(i)   for i in alist:    print(i)    while True:    try:        print(next(iter_list))    except StopIteration:        break
复制代码


可迭代对象和迭代器可以通过 for 循环访问对象中的元素;另外迭代器还可以通过 next()函数依次获取对象中的元素,如果没有元素时会抛出异常。其实 for 循环访问迭代器时内置了异常控制。


3.如何构建自己的迭代器和可迭代对象



class ADasetSet(object): def __init__(self, data): self.data = data def __getitem__(self, index): process_data = self.data[index] + index return process_data def __len__(self): return len(self.data) def __repr__(self): return "data is {}".format(data)
data = [1, 10, 100]dataset = ADasetSet(data)print(isinstance(dataset, Iterable))print(isinstance(dataset, Iterator))print(isinstance(iter(dataset), Iterator))print(dataset)for i in dataset: print(i)
# False# False# True# data is [1, 10, 100]# 1# 11# 102
复制代码


可以通过实现__getitem__函数和 iter 使得对象变成迭代器, pytorch 中的 dataloder 的输入基本上就是这么写的。__getitem__要求迭代对象的 index。


class BDasetSet(object):    def __init__(self, data):        self.data = data        self.index = 0            def __iter__(self):        return self            def __next__(self):        if self.index < len(self.data):            process_data = self.data[self.index] + self.index            self.index = self.index + 1            return process_data        else:            raise StopIteration        def __len__(self):        return len(self.data)        def __repr__(self):        return "data is {}".format(data)
data = [1, 10, 100]dataset = BDasetSet(data)print(isinstance(dataset, Iterable))print(isinstance(dataset, Iterator))print(isinstance(iter(dataset), Iterator))print(dataset)for i in dataset: print(i)# True# True# True# data is [1, 10, 100]# 1# 11# 102
复制代码


标准的迭代器对象是需要实现__iter____next__两个功能,重要的是__next__来实现对你所需要迭代的对象进行元素访问。__next__并不需要迭代器的索引,也可认为是无状态下访问迭代对象(只与前一个状态有关)。


4.python 内置的迭代器方法


  • python 中有许多好用的迭代器,主要是内置和在itertools包中

  • accumulate:累积函数

  • enumerate: 提供迭代器的索引,十分有用

  • map: 映射函数

  • zip: 组合函数

  • chain:合并函数

  • reversed: 反转函数

  • 条件判断函数:all 和 any


import itertoolsdata = [1, 2, 8, 4, 5]print(list(itertools.accumulate(data, max)))print(list(itertools.accumulate(data)))# [1, 2, 8, 8, 8]# [1, 3, 11, 15, 20]
list(enumerate(data))# [(0, 1), (1, 2), (2, 8), (3, 4), (4, 5)]
tmap = map(lambda a,b :(a, b), range(5), data)list(tmap)# [(0, 1), (1, 10), (2, 100)]
list(zip(range(5), data, range(1,6)))# [(0, 1, 1), (1, 2, 2), (2, 8, 3), (3, 4, 4), (4, 5, 5)]

list(itertools.chain(range(5), data, range(1,6)))# [0, 1, 2, 3, 4, 1, 2, 8, 4, 5, 1, 2, 3, 4, 5]

list(reversed(data))# [5, 4, 8, 2, 1]
all([1,0,0]), any([1,2,3])# (False, True)
复制代码


5.总结

这里和大家一起回顾了下 python 中的迭代器,总结如下:

  • 实现了__iter____next__的对象就是一个迭代对象

  • 通过 next()访问迭代器的下一个元素,直到抛出 StopIteration

  • 通过实现__getitem__函数和 iter()使得对象变成迭代器

  • 通过 isinstance 判断是否是 Iterable 还是 Iterator

  • 迭代器的好处就是可以迭代访问对象的元素,而不需要关注其索引位置,也就是在访问完当前元素之后这部分的内存损耗可以 del 掉,节省内存

  • 有用的参考:https://nvie.com/posts/iterators-vs-generators/




发布于: 刚刚阅读数: 3
用户头像

AIWeker

关注

公众号:人工智能微客(aiweker) 2019.11.21 加入

人工智能微客(aiweker)长期跟踪和分享人工智能前沿技术、应用、领域知识,不定期的发布相关产品和应用,欢迎关注和转发

评论

发布
暂无评论
python小知识-rethinking python 迭代器_Python_AIWeker_InfoQ写作社区