2007-07-17
Python Cookbook 2.13 使用类C++的流操作语法
需求:
你喜欢C++操作I/O的方式,使用操作符(不同的对象对输入其的数据有不同的处理)来处理,也想在Python这样做.
讨论:
Python允许你重载操作符,通过重写特定的方法(特定方法指那些命名中以两个下划线开始和结束的方法).要使用<<做为输出,就像C++中那样,需要定义一个输出流操作类并定义函数__lshift__:
class IOManipulator(object):
def _ _init_ _(self, function=None):
self.function = function
def do(self, output):
self.function(output)
def do_endl(stream):
stream.output.write ('\n')
stream.output.flush( )
endl = IOManipulator(do_endl)
class OStream(object):
def _ _init_ _(self, output=None):
if output is None:
import sys
output = sys.stdout
self.output = output
self.format = '%s'
def _ _lshift_ _(self, thing):
''' the special method which Python calls when you use the <<
operator and the left-hand operand is an OStream '''
if isinstance(thing, IOManipulator):
thing.do (self)
else:
self.output.write(self.format % thing)
self.format = '%s'
return self
def example_main( ):
cout = OStream( )
cout<< "The average of " << 1 << " and " << 3 << " is " << (1+3)/2 <<endl
# emits The average of 1 and 3 is 4
if _ _name_ _ == '_ _main_ _':
example_main( )
封装Python的类文件对象来模拟C++操作是比较容易的,本节讲了如果用<<来实现插入操作.本节也实现了一个IOManipulator类(向C++中一样)来实现对流的任意插入操作,也预定义了endl(猜猜从哪里来的?)来实现换行和刷新缓冲区.
在类OStream的实例中,我们保留了一个format属性, 并在每次调用sys.stdout.write后,将其值设置为默认的'%s',这样做是因为你可以构造自己需要的流输出格式,如:
def do_hex(stream):
stream.format = '%x'
hex = IOManipulator(do_hex)
cout << 23 << ' in hex is ' << hex << 23 << ', and in decimal ' << 23 << endl
# 输出 23 in hex is 17, and in decimal 23
有些人喜欢C++的cout<<something写法,有些人不喜欢.在Python中,我们可以使用更简单和可读的代码:
print>>somewhere, "The average of %d and %d is %f\n" % (1, 3, (1+3)/2)
这是Python方式的写法(和C很像).一切都取决于你更多使用C++还是C.不过无论怎样,本节都给出了选则方案,即使你不会使用本节讨论的内容,也能从其中看到在Python中进行操作符重载是很简单和方便的.
你喜欢C++操作I/O的方式,使用操作符(不同的对象对输入其的数据有不同的处理)来处理,也想在Python这样做.
讨论:
Python允许你重载操作符,通过重写特定的方法(特定方法指那些命名中以两个下划线开始和结束的方法).要使用<<做为输出,就像C++中那样,需要定义一个输出流操作类并定义函数__lshift__:
class IOManipulator(object):
def _ _init_ _(self, function=None):
self.function = function
def do(self, output):
self.function(output)
def do_endl(stream):
stream.output.write ('\n')
stream.output.flush( )
endl = IOManipulator(do_endl)
class OStream(object):
def _ _init_ _(self, output=None):
if output is None:
import sys
output = sys.stdout
self.output = output
self.format = '%s'
def _ _lshift_ _(self, thing):
''' the special method which Python calls when you use the <<
operator and the left-hand operand is an OStream '''
if isinstance(thing, IOManipulator):
thing.do (self)
else:
self.output.write(self.format % thing)
self.format = '%s'
return self
def example_main( ):
cout = OStream( )
cout<< "The average of " << 1 << " and " << 3 << " is " << (1+3)/2 <<endl
# emits The average of 1 and 3 is 4
if _ _name_ _ == '_ _main_ _':
example_main( )
封装Python的类文件对象来模拟C++操作是比较容易的,本节讲了如果用<<来实现插入操作.本节也实现了一个IOManipulator类(向C++中一样)来实现对流的任意插入操作,也预定义了endl(猜猜从哪里来的?)来实现换行和刷新缓冲区.
在类OStream的实例中,我们保留了一个format属性, 并在每次调用sys.stdout.write后,将其值设置为默认的'%s',这样做是因为你可以构造自己需要的流输出格式,如:
def do_hex(stream):
stream.format = '%x'
hex = IOManipulator(do_hex)
cout << 23 << ' in hex is ' << hex << 23 << ', and in decimal ' << 23 << endl
# 输出 23 in hex is 17, and in decimal 23
有些人喜欢C++的cout<<something写法,有些人不喜欢.在Python中,我们可以使用更简单和可读的代码:
print>>somewhere, "The average of %d and %d is %f\n" % (1, 3, (1+3)/2)
这是Python方式的写法(和C很像).一切都取决于你更多使用C++还是C.不过无论怎样,本节都给出了选则方案,即使你不会使用本节讨论的内容,也能从其中看到在Python中进行操作符重载是很简单和方便的.