文件

正如先前提到的,文件是存取信息的常见方式,而且许多python库 提供了"file-like"类文件对象,以便能使用文件相关的函数。一个类文件对象不需要配备下面所有的方法,只要那些需要的正确函数。至于文件的约 定,对象自由实现读,写或者读写。不是所有这里列出的方法,只需要最常用的即可。文件方法的完整列表参见python 标准库文档,详情可到文档中查看。

read(self, [size])

从对象或者它的信息源获取数据。选项size参数是获取的字节数,如果省略,这个方法就返回尽可能多的字节数。(通常是整个文件,如果可能的话,或者网络接口所容许的字节数)

write(self, str)

把指定的str,写到对象或者它的信息源。

close(self)

关闭文件,然后文件就不再被访问了。用来释放已经被分配的内存,提交对象的内容到磁盘上,或者仅仅是满足约定。即使这个方法不提供任何特殊功能,它也要提供的,防止不必要的错误。

** 一个非常松散的约定 **

类 文件(File-like)对象有很多不同的形式,因为这个约定是python中定义最松散的。有一些特性,从缓存输出到随机存取数据,有时是没有相对应 的,因此这种情况下对象将不只实现这些对应的方法。比如,django的HttpResponse对象,第7章要描述的,只允许按序列写,因此它不要实 现,read(), seek()或tell(),当使用时用这些特定的文件操作库时,会引发错误。

****

迭代

如果把一个对象传入内置函数iter(),返回一个迭代器的话,这个对象就是可迭代的(iterable),iter()通常是隐式被调用,比如在for循环中使用。所有的列表,元组和字典都是可迭代的,任何采用新的类定义方式的类都可以成为可迭代的,只要定义了下列的方法。

__iter__(self)

这个方法是由iter()隐式调用的,它负责返回一个迭代器,python用迭代器从一个对象中获取数据明细。通过一个生成器函数这样的定义方法,返回的迭代器是隐藏的,生成器看下面的“Generation”部分。

>>> class Fibonacci(object):
...     def __init__(self, count):
...        self.count = count
...     def __iter__(self):
...        a, b = 0, 1
...        for x in range(self.count):
...            if x < 2:
...                yield x
...            else:
...               c = a + b
...               yield c
...               a, b = b, c
...
>>> for x in Fibonacci(5):
...     print x
...
0
1
1
2
3
>>> for x in Fibonacci(10):
...     print x,
...
0 1 1 2 3 5 8 13 21 34

迭代器

当伴随一个对象iter()被调用时,是期待返回一个迭代器,然后为这个对象从序列中获取明细。迭代器是一个简单的方法,它是单向的游历可用的明细,一次只返回一个,直到没有更多的可用。对更大的集合,一个个访问明细比一次把他们放入一个列表中更有效。

next(self)

迭代器只要求有这个方法,它返回一个单一的明细。这个明细怎样获取依赖于迭代器的设计,但是它必须只返回一个明细项。这个明细项被调用迭代器的代码处理过之后,要获取下一个明细项时,next()再次被调用。

一 旦没有明细项返回,next()也负责告诉python停止使用这个迭代器,并从循环中移出。这是由抛出StopIteration异常来完成。 python将继续调用next(),直到异常抛出。这是一个无限循环。StopIteration能优雅的停止循环或者用另外一个异常来表明更严重的问 题。

class FibonacciIterator(object):
    def __init__(self, count):
        self.a = 0
        self.b = 1
        self.count = count
        self.current = 0

    def next(self):
        self.current += 1
        if self.current > self.count:
            raise StopIteration
        if self.current < 3:
            return self.current - 1
        c = self.a + self.b
        self.a = self.b
        self.b = c
        return c

    def __iter__(self):
        # Since it's already an iterator, this can return itself.
        return self

class Fibonacci(object):
    def __init__(self, count):
        self.count = count

    def __iter__(self):
        return FibonacciIterator(self.count)

注意,迭代器不需要为了正确的使用而去明显地定义__iter__(),但是要包含那个方法,允许迭代器在循环中正确地使用。

生成器

正如在Fibonacci例子演示的,生成器是一个方便的快捷方式,不必定义一个单独的类就可以用来创建一个迭代器。python使用yield语句,来标识一个函数作为生成器,它的行为和其他的函数是有所不同的。

当 调用一个生成器的函数时,python不会立即执行一点代码。相反,它返回一个迭代器,next()才会开始调用函数的内容,直到第一个yield发生的 地方。yield语句给出的表达式,是被用作next()方法的返回值,从而不管什么代码调用生成器,都能得到一个值。

下一次 next()在迭代器中被调用,python继续在生成器离开的位置执行这个生成器函数,同时原封不动地保留所有变量。只要python遇到yield语 句就重复上述过程,典型的情况就是使用一个循环函数来保持yielding变量。当这个函数不再生成一个值时,就算结束,迭代器自动抛出 StopIteration,表明循环应该结束,代码的其他部分继续执行。

序列

可 迭代简单地描述一个一次获取一个值的对象,(这段很怪,意译了)(有一种数据类型)他们的值通常是通过一个单一对象提前获知与收集的。这就是序列。最常见 的类型是列表和元组。作为可迭代的类型,序列也是用__iter__()方法来一个一个返回他们的值,但是这些值是提前获知的,有些附加的特性是可用的。

__len__(self)

因为所有的值是可用的,序列有一个特定的长度,是使用内置函数len()来决定。这背后,len()检查这个给定的对象是有__len__()方法,并获取这个序列的长度值。为了完成这个任务,__len__()应该返回一个整数,这个序列的明细项的总数。

从技术上,__len__()不要求所有的值都提前知晓,只要至少知道有多少值就可以。既然不可能是部分明细项--它要么存在,要么不存在--__len__()应该总是返回一个整数。如果不这样,len()将强制生成一个整数。

>>> class FibonacciLength(Fibonacci):
...     def __len__(self):
...         return self.count
...
>>> len(FibonacciLength(10))
10
>>> len(FibonacciLength(2048))
2048

__getitem__()和__setitem__()

一个序列所有的值都已经排序的,因此用索引存取序列的每个值是可能的。既然这个存取类型的语法和字典类型的键是一致的,python就使用以前字典描述过的相同的两个方法。这允许一个序列定制个别值怎样来存取,或者限制设置新值到序列,让它只读。