2015-11-08 2 views
-1

Я читаю питона кулинарной 2nd, одного образца в "глава 2,13 Использование C++ - как iostream Синтаксис«, я пытаюсь понять, как самостоятельно работы в в коде.перегрузки питон оператор «<<», как C++ iostream

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 

«я» является <__main__.OStream object at 0x7fc28cd92410>, я знаю, что это экземпляр класса OStream, может быть, может быть принято в качестве указателя C.

+1

'return self' требуется, потому что вы используете' << 'на выходе первой операции' '' '' '' и так далее ... –

+0

Обратите внимание, что если функция пропускает 'return', python делает' return None'. Следовательно, ошибка, которую вы видите ('<<' возвращает 'None' и' None << x', не определена). – Bakuriu

+0

В любом случае 'return self' ** не требуется ** строго. Вы должны положить 'return something', но это' something' может быть чем-то другим, как новый 'OStream'. – Bakuriu

ответ

2

отвечу на вопросы, вы положили в комментарии:


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 класс может выполнять функцию (см ниже, IOManipulator.do) на выходной поток.

def do(self, output): 
    self.function(output) 

Для максимального количества путаницы, первый self в этом фрагменте кода НЕ self вы прошли к нему в OStream! self вы переходите на thing.do, устанавливается как переменная output.


return self # <- why return a "self" here? 

Вы возвратите экземпляр OStream здесь, так что вы можете операции цепи. Обратите внимание, что python анализирует линию a << b << c как (a << b) << c. Часть (a << b) должна вернуть свое обновленное «я», чтобы затем иметь возможность делать << c на нем и иметь смысл. Если вы прокомментируете return self, вы получите None << c, потому что тогда функция вернет None.


self.format 

Я не уверен, что задумал автор с этим, кажется ненужным. Строка self.output.write(self.format % thing) также может быть записана как self.output.write(str(thing)).


Как заметка на полях: это может быть примером того, как можно реализовать новый оператор, но этот конкретный оператор страшно непитоновский: это привело бы к очень уродливому и запутанному коду. В реальном мире попробуйте использовать функции, которые уже есть в языке.