我正在尝试在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"""
...
我有侦听特定套接字的套接字侦听器,并调用相关类(MyDeviceType1
或MyDeviceType2
),如:
conn, address = socket.accept()
...
thread.start_new_thread(MyDeviceType1(db_connector).handle_data, ())
这个结构对我来说都很好,也很有用。一个设备( MyDevice )可能有许多子类型( MyDeviceType1 , MyDeviceType2 ),它们继承了基类。
并且有多种类型的基本设备。所以 OtherDevice 包含子类型 OtherDeviceType1 等。
MyDevice
和OtherDevice
的工作原理完全不同,因此它们是基本类型,底层代码在所有这些类型中都有很大不同。
我也有一些附加功能。这些功能可用于几乎所有设备基类型的一个或两个子类型。
所以我想准备一个可重用(可插入)的类,它可以由任何需要这些功能的子类继承。
class MyAddOn(object):
def remove_unusable_data(self):
...
def categorize_data(self):
super ???
self.remove_unusable_data()
这是我卡住的部分。由于这是一个独立的模块,因此不应继承MyDevice
或OtherDevice
等,但并非所有子设备类型都使用这些功能,我无法从{{1}继承MyDevice
也是。
只有逻辑方法,从MyAddOn
和MyDeviceSubType1
继承子类型MyDevice
MyAddOn
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)
正在触发super
但不会触发Mydevice.categorize_data
有没有办法使用MyAddOn.categorize_data
调用触发MyAddOn
方法,或者我不需要单独调用该类方法?应该调用super
和MyDevice.categorize_data
。
答案 0 :(得分:2)
这在python中称为协作多重继承,并且工作得很好。
您所谓的“Addon”类通常称为“Mixin”。
只需调用Mixin类中的super
方法:
class MyAddOn(object):
def remove_unusable_data(self):
...
def categorize_data(self):
super(MyAddon,self).categorize_data()
self.remove_unusable_data()
我想注意一些事情:
在此处调用super
似乎违反直觉,因为MyAddon
的父级没有名为categorize_data
的属性,并且您希望此注释失败。
这是super
功能发挥作用的地方。 Some认为这种行为是python的最佳选择。
与 C ++ 或 Java 不同,super
函数不一定会调用类的父类。事实上,不可能事先知道super
将调用哪个函数,因为它将在运行时基于method resoltion order来确定。
super
应该被称为next
,因为它将调用继承树中的下一个方法。
对于Mixins,即使你继承自object
,调用super也特别重要。
有关详细信息,我建议观看Raymond Hettinger在2015年pycon Super considered Super上的精彩演讲。
这是在python中使用的优秀模式。这是我在编写符合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 ...
现在您收到一个功能请求,在特定情况下,BaseClassA
和BaseClassB
都应实现功能X.
根据开放式关闭,您不必触及现有代码来实现该功能,并且根据DRY,您不应该重复该代码。
解决方案是创建一个FeatureMixin
并创建从子类和mixin继承的空子类:
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