4.6 其他的一些抽象基类

    接下来,我们会介绍其他的一些有趣的抽象基类,它们很少被扩展。但这并不意味着这些类很少被使用,只是这些抽象基类的具体实现很少需要扩展和修改。

    我们也会介绍collections.abc.Iterator中定义的迭代器。同时,我们还会介绍上下文管理器带来的不同的实现方式。这和其他的抽象基类的定义不尽相同。在第5章“可调用对象和上下文的使用”中,我们会详细探讨这个内容。

    4.6.1 迭代器的抽象基类

    当我们在for语句中使用一个可迭代的容器时,Python会隐式地创建一个迭代器。所以我们几乎不用关心迭代器本身。即使有时候我们真的需要关心迭代器的细节,也很少需要扩展或者修改现有的实现。

    我们可以通过iter()函数来剖析Python使用的隐式迭代器,可以用下面的方式和迭代器进行交互。

    >>> x = [ 1, 2, 3 ]
    >>>iter(x)
    <list_iterator object at 0x1006e3c50>
    >>>x_iter = iter(x)
    >>>next(x_iter)
    1
    >>>next(x_iter)
    2
    >>>next(x_iter)
    3
    >>>next(x_iter)
    Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
    StopIteration
    >>>isinstance(x_iter, collections.abc.Iterator )
    True

    我们创建一个基于列表对象的迭代器,然后调用next()函数来遍历列表中的值。

    最后的isinstance()表达式确定了这个迭代器对象是collections.abc.Iterator的一个实例。

    大多数时候,我们会使用集合类自己创建的迭代器。但是,当我们想创建自己的集合类型或者扩展一个集合类时,就可能需要创建一个不一样的迭代器。在第6章“创建容器和集合”中,我们会详细探讨这个内容。

    4.6.2 上下文和上下文管理器

    一个上下文管理是和with语句一起使用的。当我们写了如下的代码时,就说明我们正在使用上下文管理器。

    with function(arg) as context:
      process( context )

    在上面的例子中,function(arg)创建了上下文管理器。

    一个常用的上下文管理器是一个文件。当打开文件时,我们应该创建一个会自动关闭文件的上下文管理器。所以,我们几乎应该总是以下面的方式操作文件。

    with open("some file") as the_file:
      process(the_file )

    with语句中的代码执行完成后,Python可以保证文件一定会正确地关闭。Contextlib模块提供了一些用于创建上下文管理器的工具。这个库没有提供任何抽象基类,而是提供了装饰器和contextlib.ContextDecorator基类,其中装饰器会将简单的函数转成上下文管理器,contextlib.ContextDecorator基类可以被扩展并创建一个上下文管理器类。

    在第5章“可调用对象和上下文的使用”中,我们会详细讲解上下文管理器。