переопределение обратных вызовов, избегая загрязнения атрибута - PullRequest
1 голос
/ 13 мая 2010

У меня есть класс, который имеет несколько обратных вызовов и собственный интерфейс, например:

class Service:
     def __init__(self):
         connect("service_resolved", self.service_resolved)

     def service_resolved(self, a,b c):
         ''' This function is called when it's triggered 
             service resolved signal and has a lot of parameters'''

функция connect - это, например, gtkwidget.connect, но я хочу, чтобы это соединение было более общим, поэтому я решил использовать подход "витой как":

class MyService(Service):

   def my_on_service_resolved(self, little_param):
          ''' it's a decorated version of srvice_resolved '''
   def service_resolved(self,a,b,c):
       super(MyService,self).service_resolved(a,b,c)
       little_param = "something that's obtained from a,b,c"
       self.my_on_service_resolved(little_param)

Так что я могу использовать MyService, переопределив my_on_service_resolved.

Проблема заключается в "атрибутах" загрязнения. В реальной реализации Service имеет некоторые атрибуты, которые могут случайно переопределяться в MyService и тех, кто подкласс MyService.

Как я могу избежать загрязнения атрибутов?

То, что я подумал, - это подход типа «обертки», но я не знаю, хорошее ли это решение:

class WrapperService():
    def __init__(self):
        self._service = service_resolved
        # how to override self._service.service_resolved callback?
    def my_on_service_resolved(self,param):
        '''
        '''

1 Ответ

3 голосов
/ 13 мая 2010

Предотвращение случайных столкновений с производными классами является причиной, по которой существует подход именования «двойное ведение-подчеркивание»: если вы называете атрибут в классе Service __foo, компилятор Python внутренне «искажает» это имя до _Service__foo, что делает случайные столкновения маловероятными. Увы, не невозможно: подкласс может также иметь имя Service (и жить в другом модуле), а также имеет свой собственный атрибут __foo ... который будет назван- Точно так же искалечено, что снова привело к конфликту. Улучшения включают в себя именование базовых классов BaseService и т. П., Используя тот факт, что производный класс вряд ли будет назван Base как угодно. Но, в конце концов, нет альтернативы четкому документированию такого соглашения (по крайней мере, если подклассы будут написаны программистами с небольшим опытом работы с Python).

Я не думаю, что проблема "случайного столкновения" достаточна для того, чтобы заставить вас полностью отказаться от подкласса (в пользу использования исключительно обтекания), что в принципе является единственным способом избежать случайного столкновения имен для определенных . Подход, который вы называете «скрученным» (и на самом деле это случай шаблона проектирования «Шаблонный метод»), вполне жизнеспособен, и сочетание реальной практики именования и документирования ваших вариантов проектирования в реальной практике оказывается достаточным, чтобы избежать его "столкновение" рисков.

...