“流”是个不简单的东西。从FILE *开始初具雏形,到C++
iostream,到Java繁杂的流系统,到Boost.iostreams,流机制从一种貌似可有可无的小玩意,到在实践中大显威力,最后直到以一种全新的程序设计哲学引发人们的深思——尽管实际上,和所有新潮语言里面新奇的玩意一样,这在计算机科学中从来也不是什么新鲜东西,而是几十年前就完备的理论。然而在这里,我们抛开理论,只来讨论一个通俗的问题:如果你曾为其他语言中强大的流机制而曾经沧海,现在你使用了Python,会很自然提出问题:Python的流机制又在哪里?
作为一种流行而完备的语言,Python没有流机制是不可想像的。我们打开Python的文档搜索stream关键字,几乎一无所获。那么,在其他语言中会很自然的想到用流的那些地方,在Python中又该怎么办?我们看到的只有file类,socket类,顶多fd等一些貌似原始的部件,我们找不到任何Java流的对应物。也许会开始感叹了,缺少这种完备的功能体系,真是思想上的一大缺憾,也许又是Python为实用功利主义付出的牺牲吧,或者你已经开始搜索有没有好的第三方的Python流库,甚至开始计划自己写一个了……
然而,我们不知道,实际上Python不仅已经有了自己的完备的流机制,而且不借助任何第三方库,甚至都不用导入任何一个内置的包。——不可思议,那,居然能称得上完备?且看Java那些,任何一个踏实的人都难以相信这种无中生有。这也是对的,我们确实找不到现成的SocketStream、FilterStream和StringStream类,然而Python提供了优美的机制,让我们可以轻易地自己实现它们。——靠,好失望,到头来还得自己写!写起来哪是那么简单的,且看java.io的源代码……
好吧,为了证明这种简单,我们就来实现几个简单的流。第一个用来读取文件中的字节,第二个用来过滤流中的字节,第三个将流进的数据打印出来。
def FileStream(filename):
try:
f = open(filename)
for line in f:
for byte in line:
yield byte
except
StopIteration, e:
f.close()
return
def FilterStream(source, condition):
try:
while True:
byte = source.next()
if condition(byte):
yield byte
except
StopIteration, e:
return
def PrintStream(source):
try:
while True:
byte = source.next()
print byte
except
StopIteration, e:
return
然后写一行语句来测试全部这三个流:
PrintStream(FilterStream(FileStream('some_file'), str.islower))
可以看见结果,打印出了文件中的所有小写字母。熟悉Haskell的朋友是否有种相识的感觉?
不错,我们所指的,Python所提供的优美的机制,不是别的,正是你已经很熟悉了的生成器!忘掉java.io中大大小小的、需要费心统一接口的那些类吧,更要忘掉boost.iostreams中那些欠揍的复杂概念,Python中用一个没几行的函数,就能实现同样的功能。无论是无中生有的信源型读取流,还是有进有出的过滤/转换/处理流,还是白吞数据的信宿型写入流,都可以如此简单的实现,并且简单地对接起来,形成蜘蛛网般的数据流动通路。
这样看来,Python中没有提供有形的stream设施,不仅不是功利导致的忽略,甚至有可能是一种良苦用心,正因为基础设施太强大了,所以很怕主动提供的有限几种流实例限制了你的想象力发挥。