压倒回调避免属性污染

时间:2010-05-13 16:07:33

标签: python asynchronous

我有一个类有一些回调和它自己的接口,类似于:

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)

所以我可以通过覆盖my_on_service_resolved来使用MyService。

问题是“属性”污染。在实际实现中,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 个答案:

答案 0 :(得分:3)

避免与派生类的意外冲突是存在“双引导下划线”命名方法的原因:如果在类Service __foo中命名属性,Python编译器将在内部“破坏”该名称为_Service__foo,不太可能发生意外冲突。唉,并非不可能:子类可能被命名为Service(并且存在于另一个模块中),而具有自己的__foo属性。这将被命名为完全相同的方式,导致再次发生冲突。改进包括命名基类BaseService等,利用派生类不太可能被命名为Base的事实。但是,最后,除了明确记录这样的约定之外别无选择(至少如果子类将由具有很少Python经验的程序员编写)。

我不认为“意外冲突”问题足以迫使你完全放弃子类化(赞成使用独家包装),这基本上是避免意外名称冲突的唯一方法某些。你称之为“扭曲式”的方法(实际上是模板方法设计模式的一种情况)是非常可行的,在现实生活中,命名和文档设计选择的混合证明足以避免它的“冲突”风险。