Python 可迭代对象、迭代器、生成器

2019-12-07  本文已影响0人  C_Z_Q_

1.可迭代的对象

定义:可迭代的对象(Iterable)是指使用iter()内置函数可以获取迭代器(Iterator)的对象

1.1 判断对象是否可迭代

检查对象x能否迭代,最准确的方法是:调用iter(x)函数,如果不可迭代,会抛出TypeError异常。这比使用isinstance(x, abc.Iterable)更准确,因为iter(x)函数会考虑到遗留的__getitem__(index)方法,而abc.Iterable类则不会考虑

1.2 __getitem__()

下面构造一个类,它实现了__getitem__()方法。可以给类的构造方法传入包含一些文本的字符串,然后可以逐个单词进行迭代:

'''创建test.py模块'''
import re
import reprlib

RE_WORD = re.compile('\w+')

class Sentence:
    def __init__(self, text):
        self.text = text
        self.words = RE_WORD.findall(text)

    def __getitem__(self, index):
        return self.words[index]

    def __len__(self):  # 为了让对象可以迭代没必要实现这个方法,这里是为了完善序列协议,即可以用len(s)获取单词个数
        return len(self.words)
    def __repr__(self):
        return 'Sentence({})'.format(reprlib.repr(self.text))

测试Sentence实例能否迭代:

In [1]: from test import Sentence  # 导入刚创建的类

In [2]: s = Sentence('I love Python')  # 传入字符串,创建一个Sentence实例

In [3]: s
Out[3]: Sentence('I love Python')

In [4]: s[0]
Out[4]: 'I'

In [5]: s.__getitem__(0)
Out[5]: 'I'

In [6]: for word in s:  # Sentence实例可以迭代
   ...:     print(word)
   ...:     
I
love
Python

In [7]: list(s)  # 因为可以迭代,所以Sentence对象可以用于构建列表和其它可迭代的类型
Out[7]: ['I', 'love', 'Python']

In [8]: from collections import abc

In [9]: isinstance(s, abc.Iterable)  # 不能正确判断Sentence类的对象s是可迭代的对象
Out[9]: False

In [10]: iter(s)  # 没有抛出异常,返回迭代器,说明Sentence类的对象s是可迭代的
Out[10]: <iterator at 0x7f82a761e5f8>

1.3. __iter__()

用法:
__iter__()
\t return 返回迭代器

1.4 iter()函数的补充

iter()函数有两种用法:

2. 迭代器

一种惰性获取数据项的方式,即按需一次获取一个数据项。这就是迭代器模式(Iterator pattern)

迭代器是这样的对象:实现了无参数的__next__()方法,返回序列中的下一个元素,如果没有元素了,就抛出StopIteration异常。即,迭代器可以被next()函数调用,并不断返回下一个值

在 Python 语言内部,迭代器用于支持: for 循环。构建和扩展集合类型逐行遍历文本文件列表推导、字典推导和集合推导元组拆包调用函数时,使用 * 拆包实参

2.1 判断对象是否为迭代器

检查对象x是否为迭代器最好的方式是调用isinstance(x, abc.Iterator)
Python中内置的序列类型,如list、tuple、str、bytes、dict、set、collections.deque等都是可迭代的对象,但不是迭代器; 生成器一定是迭代器

2.2 __next__()__iter__()

标准的迭代器接口:

2.3 next()函数获取迭代器中下一个元素

除了可以使用for循环处理迭代器中的元素以外,还可以使用next()函数,它实际上是调用iterator.__next__(),每调用一次该函数,就返回迭代器的下一个元素。如果已经是最后一个元素了,再继续调用next()就会抛出StopIteration异常。一般来说,StopIteration异常是用来通知我们迭代结束的
或者,为next()函数指定第二个参数(默认值),当执行到迭代器末尾后,返回默认值,而不是抛出异常

2.4 可迭代的对象与迭代器的对比

总结:
(1) 迭代器要实现__next__()方法,返回迭代器中的下一个元素
(2) 迭代器还要实现__iter__()方法,返回迭代器本身,因此,迭代器可以迭代。迭代器都是可迭代的对象
(3) 可迭代的对象一定不能是自身的迭代器。也就是说,可迭代的对象必须实现__iter__()方法,但不能实现__next__()方法

3. 生成器

在Python中,可以使用生成器让我们在迭代的过程中不断计算后续的值,而不必将它们全部存储在内存中

3.1 生成器函数

3.2 生成器表达式

3.3 增强生成器

使用.send()方法
使用方法:对象 . send(x) #x 为发送的数据
.__next__()方法一样,.send()方法使生成器前进到下一个yield语句。不过,.send()方法还允许调用方把数据发送给生成器,即不管传给.send()方法什么参数,那个参数都会成为生成器函数定义体中对应的yield表达式的值。也就是说,send()方法允许在调用方生成器之间双向交换数据,而.__next__()方法只允许调用方从生成器中获取数据

查看生成器对象的状态:
可以使用 inspect.getgeneratorstate(...)函数查看生成器对象的当前状态:

  • 'GEN_CREATED': 等待开始执行
  • 'GEN_RUNNING': 正在被解释器执行。只有在多线程应用中才能看到这个状态
  • 'GEN_SUSPENDED': 在yield表达式处暂停
  • 'GEN_CLOSED': 执行结束

3.4 yield from

yield from 后面需要加的是可迭代对象,它可以是普通的可迭代对象,也可以是迭代器,甚至是生成器。

上一篇 下一篇

猜你喜欢

热点阅读