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

2024-10-01 09:15:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试用python2.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)。你知道吗

而且基本设备不止一种。因此有其他设备和子类型其他设备类型1

MyDeviceOtherDevice的工作方式完全不同,因此它们都是基本类型,而它们的底层代码也完全不同。你知道吗

我还有一些附加功能。这些功能可由几乎所有设备基本类型的一个或两个子类型使用。你知道吗

所以我想准备一个可重用(可插入)的类,它可以被任何需要这些功能的子类型继承。你知道吗

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

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

这是我坚持的部分。因为这是一个独立的模块,它不应该从MyDeviceOtherDevice等继承,但不是所有的子设备类型都在使用这些功能,我也不能从MyAddOn继承MyDevice。你知道吗

只有逻辑方法是这样的,从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都应该被调用。你知道吗


Tags: to方法self类型dbdatainitdef
1条回答
网友
1楼 · 发布于 2024-10-01 09:15:40

这在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_data的属性,您可能会期望此表示法失败。你知道吗

这就是super函数发挥作用的地方。Some认为这种行为是python的优点。你知道吗

<>与C++ +EEM>或java EEE>不同,^ {< CD1>}函数不一定调用类的父类。实际上,不可能预先知道super将调用哪个函数,因为它将在运行时根据method resoltion order决定。你知道吗

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

对于mixin,调用super尤其重要,即使您是从object继承的。你知道吗

欲了解更多信息,我建议观看Raymond Hettinger在pycon 2015的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 ...   

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

相关问题 更多 >