LINUX.ORG.RU

Вопрос по Питону


0

0

Делаю я прототипец одного сервера на пистоне

class SomeServer:
    def __init__(self, ...)
        self.__dispatcher = {"CMD1" : self.invoke_cmd1_command, \
                             "CMD2" : self.invoke_cmd2_command, \
                             "CMD3" : self.invoke_cmd3_command, \
                             "CMD4" : self.invoke_cmd4_command, \
                              ... : ...}


    def handle_some_request(self, request):
        command, arguments = extract_command_and_arguments(request)
        try:
            self.__dispatcher[command](command, arguments)
        except Exception as e:
            ... log it ...
            ... return error to client...
            ... whatever ...

Возник вопрос - этот диспатчер должен вроде быть статическим и инициализироваться при загрузке класса. Но как из статического контекста дотянуться до self я что-то не допер. Такие дела.

PS: Впрочем для прототипа и так кузяво.

★★★

> этот диспатчер должен вроде быть статическим

Ну так не используй self.

> как из статического контекста дотянуться до self я что-то не допер.

Допрешь - скажи.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>> этот диспатчер должен вроде быть статическим

>Ну так не используй self.

Методы должны быть не статическими. Надо взять из диспатчера функцию и как-то ассоциировать ее с self. Первым параметром чтоли передать?

Absurd ★★★
() автор топика

Так не прокатит?

class SomeServer:
    dispatcher = {"CMD1" : self.invoke_cmd1_command, \
                  "CMD2" : self.invoke_cmd2_command, \
                  "CMD3" : self.invoke_cmd3_command, \
                  "CMD4" : self.invoke_cmd4_command, \
                   ... : ...}

    def __init__(self, ...):
        #доступ к полям класса работает медленно
        #поэтому загоним в инстанс
        self.__dispatcher = dispatcher

true_admin ★★★★★
()
Ответ на: комментарий от LamerOk

>Чего только люди не придумают, лишь бы не пользоваться ruby...

Сконкатенировать "invoke_" и command и вызвать метод invoke_CMD* через рефлексию тоже можно. Но какбе рефлексия по нормальному должна использоваться для интерфейса с кодом который в момент написания не существует.

Absurd ★★★
() автор топика

Пока нет экземпляра класса методы будут несвязаны. Следовательно нам нужно
иметь экземпляр чтобы связать его с методами и командами.

В общем, я вижу три варианта:

1)
class Server( object ):
  
  def invoke_cmd1_command( self, ... ): ...
  def invoke_cmd2_command( self, ... ): ...
  .....
  def handle_request( self, req ):
    try:
      cmd, args = parse_request( req )
      handler = self.__routes[ cmd ]
      res = handler( self, *args )
    except Exception, e:
      .....

  __routes = {
    'CMD1' : invoke_cmd1_command,
    'CMD2' : invoke_cmd2_command,
    .....
  }

2)
class Server( object ):
  __routes = {
    'CMD1' : 'invoke_cmd1_command',  # method names as strings
    'CMD2' : 'invoke_cmd2_command',
    .....
  }  
  def invoke_cmd1_command( self, ... ): ...
  def invoke_cmd2_command( self, ... ): ...
  .....
  def handle_request( self, req ):
    try:
      cmd, args = parse_request( req )
      handler_name = self.__routes[ cmd ]
      handler = getattr( self, handler_name )
      res = handler( *args )
    except Exception, e:
      .....

3)  # вариация на тему N2
class Server( object ):
  __routes = {
    'CMD1' : 'invoke_cmd1_command',  # method names as strings
    'CMD2' : 'invoke_cmd2_command',
    .....
  }  
  def __init__( self ):
    self.__dispatch_dict = d = {}
    for k,v in self.__routes.items():
      d[ k ] = getattr( self, v )

  def invoke_cmd1_command( self, ... ): ...
  def invoke_cmd2_command( self, ... ): ...
  .....
  def handle_request( self, req ):
    try:
      cmd, args = parse_request( req )
      handler = self.__dispatch_dict[ cmd ]
      res = handler( *args )
    except Exception, e:
      .....

realsmart
()
Ответ на: комментарий от Absurd

> Но какбе рефлексия по нормальному должна использоваться ...

Мне думается, что в питоне не нужно следовать этим жабо-догмам.
Это динамический язык -- и всякие мини трюки с переходом от символьных
имён к объектам и обратно весьма распространены в мире питона (пержде всего это практично и гибко).

realsmart
()
Ответ на: комментарий от realsmart

>> Но какбе рефлексия по нормальному должна использоваться ...

>Мне думается, что в питоне не нужно следовать этим жабо-догмам.

Ну еще какбе вставлять пользовательский ввод в eval() не совсем хорошо.

Absurd ★★★
() автор топика
Ответ на: комментарий от realsmart

> Мне думается, что в питоне не нужно следовать этим жабо-догмам.

Это не жабо-догмы, это KISS principle. Вообще первый приведенный вариант был идеальным - делал ровно то, что нужно, очевидным способом, и оставлял возможность для пообъектной настройки.

> всякие мини трюки с переходом от символьных имён к объектам и обратно

...используются, когда нет другого выхода, и это явно не рассматриваемый случай.

> весьма распространены в мире питона

Чушь.

tailgunner ★★★★★
()
Ответ на: комментарий от Absurd

>>Мне думается, что в питоне не нужно следовать этим жабо-догмам.

>Ну еще какбе вставлять пользовательский ввод в eval() не совсем хорошо.

:) Я согласен, коллега.

realsmart
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.