2015-10-26 53 views
1

我想在python 2.6中创建一个可重用的应用程序。创建一个基于类的可重用应用程序

我正在开发用于监听GPS跟踪设备的服务器端脚本。该脚本正在使用套接字。

我有一个基类,它定义了处理设备发送的数据的基本方法。

class MyDevice(object): 
    def __init__(self, db) 
     self.db = db # This is the class that defines methods for connecting/using database 

    def initialize_db(self): 
     ... 

    def handle_data(self): 
     self.initialize_db() 
     ... 
     self.process_data() 

    def process_data(self): 
     ... 
     self.categorize_data() 

    def categorize_data(self): 
     ... 
     self.save_data() 

    def save_data(self): 
     ... 

该基类提供了许多设备,因为只有在设备之间的一些细微的差别。因此,我为每个设备类型创建一个类,并针对该设备进行安排。

class MyDeviceType1(Mydevice): 
    def __init__(self, db): 
     super(MyDeviceType1, self).__init__(db) 

    def categorize_data(self): 
     super(MyDeviceType1, self).categorize_data(self) 
     self.prepopulate_data() 
     ... # Do other operations specific to device 

    def prepopulate_data(self): 
     """this is specific to Type1 devices""" 
     ... 


class MyDeviceType2(Mydevice): 
    def __init__(self, db): 
     super(MyDeviceType1, self).__init__(db) 

    def categorize_data(self): 
     super(MyDeviceType1, self).categorize_data(self) 
     self.unpopulate_data() 
     ... # Do other operations specific to device 

    def unpopulate_data(self): 
     """this is specific to Type2 devices""" 
     ... 

我有套接字监听,监听特定套接字,并调用相关的类(MyDeviceType1MyDeviceType2),如:

conn, address = socket.accept() 
... 
thread.start_new_thread(MyDeviceType1(db_connector).handle_data,()) 

即结构都很好,对我来说非常有用。一个设备(MyDevice)可能有许多子类型(MyDeviceType1,MyDeviceType2),它继承了基类。

并且有多种类型的基础设备。因此,有OtherDevice亚型有OtherDeviceType1

MyDeviceOtherDevice作品完全不同,所以他们的基本类型和底层代码是所有的人都完全不同。

我也有一些附加功能。这些功能可用于几乎所有设备基本类型的一个或两个子类型。

所以我想准备一个可以被任何需要这些功能的子类型继承的可重复使用的(可插入的)类。

class MyAddOn(object): 
    def remove_unusable_data(self): 
     ... 

    def categorize_data(self): 
     super ??? 
     self.remove_unusable_data() 

这里是我卡住的部分。由于这是一个独立的模块,它不应该从MyDeviceOtherDevice等继承,但不是所有的子设备类型正在使用这些功能,我不能继承MyAddOnMyDevice了。

只有逻辑方法看起来像,从两个MyDeviceMyAddOn

class MyDeviceType1(Mydevice, MyAddOn): 
    def __init__(self, db): 
     super(MyDeviceType1, self).__init__(db) 

    def categorize_data(self): 
     >> super(MyDeviceType1, self).categorize_data(self) << 
     self.prepopulate_data() 
     ... # Do other operations specific to device 

    def prepopulate_data(self): 
     """this is specific to Type1 devices""" 

super(MyDeviceType1, self).categorize_data(self)继承亚型MyDeviceSubType1是问题的一部分。 super被触发Mydevice.categorize_data但不MyAddOn.categorize_data

有没有办法使用super通话或者在这样的方式,我不需要seperately调用类的方法来触发MyAddOn方法?应该调用MyDevice.categorize_dataMyAddOn.categorize_data

+0

为什么这样做增加的功能必须是“插件能够”? 它看起来像你的插件操作一些数据,可以通过设备获取,而且更多的是一个实现转换的效用函数。如果这不需要设备的任何状态,为什么还要把这个实用功能强加到设备上呢?从设备获取数据并将其传递给实用程序功能。 – null

+0

如果操作者希望事物可以被其他人扩展,那么类会击败实用函数。如果op在pypi上发布库,任何人都可以重新使用代码并覆盖他们不喜欢的部分。 –

回答

2

这在python中称为协作多重继承,工作得很好。

你称之为“Addon”类,通常称为“Mixin”。

只要打电话给super方法在混合类:

class MyAddOn(object): 
    def remove_unusable_data(self): 
     ... 

    def categorize_data(self): 
     super(MyAddon,self).categorize_data() 
     self.remove_unusable_data() 

我想需要注意的一些事情:

  • 的方法解析顺序是从左到右
  • 你必须致电超级
  • 您应该使用** kwargs进行协作继承

这似乎违反直觉的来电来访super,作为MyAddon父没有叫categorize_data一个属性,你会想到这个符号失败。

这就是super函数发挥作用的地方。 Some认为这种行为是关于python的最好的事情。

不像C++的Javasuper功能不一定调用类的父类。事实上,事先不可能知道super将调用哪个函数,因为它将在运行时根据method resoltion order决定。

super python应该真的叫next,因为它会调用继承树中的下一个方法。

对于Mixin而言,即使您从object继承,调用super也特别重要。

如需进一步信息,我建议从2015年PYCON


它在Python中使用一个很好的模式看雷蒙德赫廷杰对Super considered Super优秀的谈话。下面是编程结构化的应用程序服从,当我遇到经常一个模式open-closed principle

我这是在生产中使用这个库类:

class BaseClassA(object): 
    def __init__(self, **kwargs): 
     ... Do something that's important for many modules 
    def ... 

class BaseClassB(object): 
    def __init__(self, **kwargs): 
     ... Do something that's important for many modules 
    def ... 

现在你会得到一个功能要求,在特定的情况下,两个BaseClassABaseClassB应该实现功能X.

根据开 - 关,你不应该触摸现有的代码来实现该功能,根据DRY你不应该重复的代码。

的解决方案是创建一个FeatureMixin并创建从基类和混入继承空的子类:

class FeatureMixin(object): 
    def __init__(self,**kwargs): 
     ...do something specific 
     return super(FeatureMixin,self).__init__(**kwargs) 
class ExtendedA(FeatureMixin,BaseClassA): 
    pass 
class ExtendedB(FeatureMixin,BaseClassB): 
    pass 
相关问题