Python 创建基于类的可重用应用程序
我试图在Python2.6中创建一个可重用的应用程序 我正在开发用于监听GPS跟踪设备的服务器端脚本。脚本正在使用套接字 我有一个基类,它定义了处理设备发送的数据的基本方法Python 创建基于类的可重用应用程序,python,multiple-inheritance,mixins,python-2.x,code-reuse,Python,Multiple Inheritance,Mixins,Python 2.x,Code Reuse,我试图在Python2.6中创建一个可重用的应用程序 我正在开发用于监听GPS跟踪设备的服务器端脚本。脚本正在使用套接字 我有一个基类,它定义了处理设备发送的数据的基本方法 类MyDevice(对象): def_uuuinit_uuu(self,db) self.db=db#这个类定义了连接/使用数据库的方法 def初始化_db(自身): ... def句柄_数据(自身): self.initialize_db() ... self.process_data() def过程_数据(自身): ..
类MyDevice(对象):
def_uuuinit_uuu(self,db)
self.db=db#这个类定义了连接/使用数据库的方法
def初始化_db(自身):
...
def句柄_数据(自身):
self.initialize_db()
...
self.process_data()
def过程_数据(自身):
...
self.categorize_data()
def分类_数据(自身):
...
self.save_data()
def保存_数据(自身):
...
这个基类适用于许多设备,因为这些设备之间只有一些细微的差别。因此,我为每个特定的设备类型创建了一个类,并对该设备进行了特定的安排
类MyDeviceType1(Mydevice):
定义初始化(自我,数据库):
超级(MyDeviceType1,self)。\uu初始化(db)
def分类_数据(自身):
超级(MyDeviceType1,self)。对数据进行分类(self)
self.prepopulate_data()
... # 执行特定于设备的其他操作
def预填充_数据(自身):
“”“这是特定于类型1设备的”“”
...
类别MyDeviceType2(Mydevice):
定义初始化(自我,数据库):
超级(MyDeviceType1,self)。\uu初始化(db)
def分类_数据(自身):
超级(MyDeviceType1,self)。对数据进行分类(self)
self.unpopulate_数据()
... # 执行特定于设备的其他操作
def未填充_数据(自身):
“”“这是特定于类型2设备的”“”
...
我有监听特定套接字的套接字侦听器,并调用相关类(MyDeviceType1
或MyDeviceType2
),如:
conn,address=socket.accept()
...
线程。启动新线程(MyDeviceType1(db连接器)。处理数据,())
这种结构对我来说很好,也很有用。一个设备(MyDevice)可能有许多继承基类的子类型(MyDeviceType1、MyDeviceType2)
并且有不止一种类型的基本设备。因此,还有其他设备具有子类型OtherDeviceType1等
MyDevice
和OtherDevice
的工作原理完全不同,因此它们是基本类型,并且它们的底层代码都非常不同
我还有一些附加功能。几乎所有设备基本类型的一个或两个子类型都可以使用这些功能
所以我想准备一个可重用(可插入)的类,它可以被任何需要这些功能的子类型继承
类MyAddOn(对象):
def删除不可用的数据(自身):
...
def分类_数据(自身):
超级的???
self.remove_无法使用的_数据()
这是我卡住的部分。由于这是一个独立的模块,因此不应从MyDevice
或OtherDevice
等继承,但并非所有子设备类型都使用这些功能,我也不能从MyAddOn
继承MyDevice
只有逻辑方法看起来像是从MyDevice
和MyAddOn
继承子类型MyDeviceSubType1
类MyDeviceType1(Mydevice,MyAddOn):
定义初始化(自我,数据库):
超级(MyDeviceType1,self)。\uu初始化(db)
def分类_数据(自身):
>>super(MyDeviceType1,self)。对数据进行分类(self)这在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()
我想指出一些事情:
- 方法解析顺序为从左到右
- 你必须打超级电话
- 您应该使用**kwargs进行协作继承
在这里调用super
似乎是违反直觉的,因为MyAddon
的父级没有名为categorize\u data
的属性,您可能会认为这种表示法会失败
这就是super
功能发挥作用的地方。认为这种行为对Python来说是最好的。
<>与C++或java不同,超函数不一定调用类的父类。事实上,不可能预先知道super
将调用哪个函数,因为它将在运行时根据
python中的super
实际上应该被调用next
,因为它将调用继承树中的下一个方法
对于mixin,调用super尤其重要,即使您是从对象继承的
有关更多信息,我建议观看Raymond Hettinger在pycon 2015上的精彩演讲
这是一种在python中使用的优秀模式。以下是我在编写遵循以下规则的结构化应用程序时经常遇到的一种模式:
我有一个用于生产的库类:
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
根据open-close,您不必触摸现有代码来实现该功能,根据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
为什么添加的功能必须是“可插入的”?看起来你的插件操作的是一些可以由设备获取的数据,更像是一个进行转换的实用功能。如果这不需要设备的任何状态,为什么还要麻烦将此实用程序功能强制到设备上?从设备获取数据并将其传递给实用程序funct