Python 迭代器

深入理解迭代器和生成器

古之立大事者,不唯有超世之才,亦必有坚韧不拔之志 – 苏轼

迭代

迭代指得是通过重复执行某个操作,不断获取被迭代对象中得数据.每一次操作就是一次迭代

迭代是遍历得一种形式.例如我们之前学的 For 循环, 它能不断得从列表,元祖,字符串,集合,字典等容器中取出新元素,每次一个元素直至所有元素被取完.这种 for 循环就是迭代


for item in [1,2,3,4,5]:
   print(item)

# 结果 1,2,3,4,5

迭代器

迭代器得使用方法


# 迭代器 = iter(容器)

numbers = [1,2,3,4,5]

iterator = iter(numbers)

# 上面得iterator就是一个迭代器

这个迭代器用于迭代列表中的所有元素.
要使用迭代器只需要迭代器调用内置函数 next(),便可逐一获取其中所有的值


# 值 = next(迭代器)

arr = [1, 2, 3, 4, 5]
iterator = iter(arr)
print(next(iterator))
print(next(iterator))
print(next(iterator))
print(next(iterator))
print(next(iterator))
# 结果
# 1
# 2
# 3
# 4
# 5

可以看到每次调用 next()将一次返回列表中的一个值.直到所有的值被遍历一遍,此时抛出异常代表迭代终止

for 循环的迭代过程

for 循环的迭代就是通过使用迭代器来完成:

  • 对一个容器调用 iter()函数获取该容器的迭代器

  • 每次循环时对迭代器调用 next()函数,以获取一个值

  • 若捕获到异常则结束循环

什么是可迭代的

  • 从表面上看所有可用于 for 循环的对象都是可迭代的,如列表,元祖,字符串,集合,字典等容器

  • 从深层看 定义了__iter__()方法的类对象就是可迭代的.当这个类对象被 iter()函数使用时,将返回一个迭代器对象.如果对象有__iter__()方法,则可以说它支持迭代协议

判断一个已有的对象是否可迭代

  • 通过内置函数 dir()获取这个对象的所有方法,检查是否有 ‘__iter__‘

'__iter__' in dir(list)

# True

'__iter__' in dir(int)

# False
  • 使用内置函数 isinstance()判断其是否为 iterable 的对象

from collections.abc import Iterable

isinstance([1,2,3],iterable)

自定义迭代器

我们可以自己来定义迭代器类,只要在类种定义__next__()和__iter__()方法即可

  • 基本语法

class MyIterator:
     def __next__(self):
        代码块
     def __iter__(self):
         return self
  • 实例化

class PowerOfTwo:
  def __init__(self):
     self.exponent = 0  # 将每次的指数记录下来
  def __next__(self):
     if self.exponent>10:
        raise StopIteration
     else:
        result = 2 ** self.exponent
        self.exponent +=1
        return result
   def __iter__(self):
        return self

每次对迭代器使用内置函数 next()时,next()将在背后调用迭代器__next__()方法.所以迭代器的重点是__next__()方法的实现,在这个 next 方法中,我们将求职时的指数记录在对象 self.exponenth 中,求值结束时指数加 1,为下次求值做准备

对于方法__iter__()的实现,我们直接返回迭代器对象自身即可。可直接用于 for 循环

扩展 如果对象具有__iter__()和__next__()方法,则可以说它支持携带其协议

  • 实例化使用

class PowerOfTwo:
    def __init__(self):
        self.exponent = 0  # 将每次的指数记录下来

    def __iter__(self):
        return self

    def __next__(self):
        if self.exponent > 10:
            raise StopIteration
        else:
            result = 2 ** self.exponent
            self.exponent += 1
            return result


p = PowerOfTwo()

print(next(p))
print(next(p))
# 结果
# 1
# 2

迭代器的好处

  • 当我们需要逐一获取数据集合中的数据的时候,可以使用迭代器

  • 另外一方面,数据的存储时需要占用内存的。数据越大占用的内存越多.而迭代器可以不保存数据,他的数据可以在需要的时候被计算出来(节省资源)


文章作者: 雾烟云
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 雾烟云 !
  目录