将 python 运算符“<<”重载为 C++ iostream
Overload python operator "<<" as C++ iostream
我正在阅读 python 第二本食谱,“第 2.13 章使用类似 C++ 的 iostream 语法 中的一个示例“,我试图理解 self 在代码中是如何工作的。
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)
# my understanding, all above is about make a newline and flush sys.stdout,
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):
if isinstance(thing, IOManipulator):
thing.do(self)
# It make no sense to me, why the function belongs to
# another class's instance need call (self)
else:
self.output.write(self.format % thing)
self.format = '%s' # <- is it necessary? seems to be not.
return self # <- why return a "self" here?
# If comment this line out,
# python raise a TypeError when execute to the "<< 1"
# TypeError: unsupported operand type(s) for <<: 'NoneType' and 'int'
def example_main():
cout = OStream()
cout << "The average of " << 1 << " and " << 3 << " is " << (1+3)/2 << endl
if __name__ == '__main__':
example_main()
# emits:
#> The average of 1 and 3 is 2
"self" 是 <__main__.OStream object at 0x7fc28cd92410>
,我知道它是 OStream class 的实例,也许可以作为 C 指针。
我会回答你在评论中提出的问题:
if isinstance(thing, IOManipulator):
thing.do(self)
# It make no sense to me, why the function belongs to
# another class's instance need call (self)
您将 self
(输出流)传递给 thing
(这将是一个 IOManipulator
,例如 endl
操作),因此 IOManipulator
class 可以在输出流上执行函数(见下文,IOManipulator.do
)。
def do(self, output):
self.function(output)
为了最大程度的混淆,此代码段中的第一个 self
不是您在 OStream
中传递给它的 self
!您传递给 thing.do
的 self
被设置为 output
变量。
return self # <- why return a "self" here?
你 return 这里的 OStream
实例所以你可以链式操作。请注意,python 将行 a << b << c
解析为 (a << b) << c
。 (a << b)
部分需要 return 更新后的自身,以便能够对其执行 << c
并变得有意义。如果你把 return self
注释掉,你最终会得到 None << c
因为这样函数就会 return None
.
self.format
我不确定作者的意图,似乎没有必要。 self.output.write(self.format % thing)
行也可以写成 self.output.write(str(thing))
.
作为旁注:这可能是您如何实现新运算符的示例,但这个特定运算符 非常 un-pythonic:它会导致非常丑陋和混乱的代码。在现实世界中,尽量使用语言已有的特性。
我正在阅读 python 第二本食谱,“第 2.13 章使用类似 C++ 的 iostream 语法 中的一个示例“,我试图理解 self 在代码中是如何工作的。
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)
# my understanding, all above is about make a newline and flush sys.stdout,
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):
if isinstance(thing, IOManipulator):
thing.do(self)
# It make no sense to me, why the function belongs to
# another class's instance need call (self)
else:
self.output.write(self.format % thing)
self.format = '%s' # <- is it necessary? seems to be not.
return self # <- why return a "self" here?
# If comment this line out,
# python raise a TypeError when execute to the "<< 1"
# TypeError: unsupported operand type(s) for <<: 'NoneType' and 'int'
def example_main():
cout = OStream()
cout << "The average of " << 1 << " and " << 3 << " is " << (1+3)/2 << endl
if __name__ == '__main__':
example_main()
# emits:
#> The average of 1 and 3 is 2
"self" 是 <__main__.OStream object at 0x7fc28cd92410>
,我知道它是 OStream class 的实例,也许可以作为 C 指针。
我会回答你在评论中提出的问题:
if isinstance(thing, IOManipulator):
thing.do(self)
# It make no sense to me, why the function belongs to
# another class's instance need call (self)
您将 self
(输出流)传递给 thing
(这将是一个 IOManipulator
,例如 endl
操作),因此 IOManipulator
class 可以在输出流上执行函数(见下文,IOManipulator.do
)。
def do(self, output):
self.function(output)
为了最大程度的混淆,此代码段中的第一个 self
不是您在 OStream
中传递给它的 self
!您传递给 thing.do
的 self
被设置为 output
变量。
return self # <- why return a "self" here?
你 return 这里的 OStream
实例所以你可以链式操作。请注意,python 将行 a << b << c
解析为 (a << b) << c
。 (a << b)
部分需要 return 更新后的自身,以便能够对其执行 << c
并变得有意义。如果你把 return self
注释掉,你最终会得到 None << c
因为这样函数就会 return None
.
self.format
我不确定作者的意图,似乎没有必要。 self.output.write(self.format % thing)
行也可以写成 self.output.write(str(thing))
.
作为旁注:这可能是您如何实现新运算符的示例,但这个特定运算符 非常 un-pythonic:它会导致非常丑陋和混乱的代码。在现实世界中,尽量使用语言已有的特性。