gpt4 book ai didi

python - 创建基于类的可重用应用程序

转载 作者:行者123 更新时间:2023-12-01 04:21:36 25 4
gpt4 key购买 nike

我正在尝试在 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) 可能有多个继承基类的子类型 (MyDeviceType1MyDeviceType2)。

而且基础设备的类型不止一种。因此,有 OtherDevice 和子类型 OtherDeviceType1 等。

MyDeviceOtherDevice 的工作方式非常不同,因此它们是基本类型,并且底层代码在它们中都非常不同。

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

因此,我想准备一个可重用(可插入)的类,该类可以由需要这些功能的任何子类型继承。

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

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

这是我坚持的部分。由于这是一个独立的模块,它不应该从 MyDeviceOtherDevice 等继承,但并非所有子设备类型都使用这些功能,我无法继承 MyDevice 也来自 MyAddOn

只有逻辑方法看起来像,从 MyDeviceMyAddOn 继承子类型 MyDeviceSubType1

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

是否有任何方法可以使用 super 调用或以不需要单独调用该类方法的方式触发 MyAddOn 方法?应该调用 MyDevice.categorize_dataMyAddOn.categorize_data

最佳答案

这在 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
  • 您应该使用 **kwargs 进行合作继承
<小时/>

在这里调用 super 似乎违反直觉,因为 MyAddon 的父级没有名为 categorize_data 的属性,而您会期望这样表示失败。

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

C++Java不同,super函数不一定调用类的父类。事实上,不可能提前知道 super 会调用哪个函数,因为它将在运行时根据 method resoltion order 来决定。 .

python中的

super实际上应该被称为next,因为它将调用继承树中的下一个方法。

对于 Mixins 来说,调用 super 尤为重要,即使您是从 object 继承的。

如需了解更多信息,我建议观看 Raymond Hettinger 在 Super considered Super 上的精彩演讲。来自 pycon 2015。

<小时/>

这是一个在 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 ...

现在您收到一个功能请求,在特定情况下,BaseClassABaseClassB 都应实现功能 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

关于python - 创建基于类的可重用应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33614750/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com