【问题标题】:Using descriptors in a superclass to avoid code duplication in subclasses在超类中使用描述符以避免子类中的代码重复
【发布时间】:2019-12-22 00:53:15
【问题描述】:

在 python 中,我有一个基类,从中派生出一组子类。每个子类都有一些特定于子类的函数和许多独特的属性,这些属性具有使用@property 装饰器定义的getter 和setter。但是如果我有很多属性,就会导致很多代码重复,因为 getter 和 setter 都具有相同的形式。这是一个粗略的示例草图,以数据库访问为例:

class BaseClass():
    def __init__(self):
        self.handle = None

    def write(self, **kwargs):
        self.handle.write(**kwargs)

class subClass_1(BaseClass):
    def __init__(self):
        self.handle = db_connector("table1")

    @property
    def property1a(self):
        return self.handle.read('columnX')

    @property1a.setter
    def property1a(self, data):
        self.write(columnX=data)

    @property
    def property1b(self):
        return self.handle.read('columnY')

    @property1b.setter
    def property1b(self, data):
        self.write(columnY=data)

    def some_bespoke_function():
        pass

class subClass_2(BaseClass):
    def __init__(self):
        self.handle = db_connector("table2")

    @property
    def property2a(self):
        return self.handle.read('columnZ')

    @property2a.setter
    def property2a(self, data):
        self.write(columnZ=data)

    def another_bespoke_function():
        pass

有什么方法可以在 BaseClass 中定义一些东西以避免编写所有这些 @property 装饰器?理想情况下,我只需在子类中定义一些东西,例如为 SubClass_1 定义 self.mapping = {'property1a':'columnX', 'property1a':'columnX'} 和为 SubClass_2 定义 self.mapping = {'property2a':'columnZ'}

【问题讨论】:

    标签: python python-decorators python-descriptors


    【解决方案1】:

    回答我自己的问题:解决方案似乎是在基类中使用__getattr__,(我没有意识到)只有在属性不存在时才会调用它。所以这里的关键是(奇怪地) 根本不定义属性,而是捕获对这些不存在的“属性”的读取和写入调用,并根据需要触发函数。完全不需要装饰器:

    class BaseClass():
        col_mapping = {}
        def __init__(self):
            self.handle = None
    
        def __getattr__(self, name):
            if name in col_mapping:
                return self.handle.read(col_mapping[name])
            raise AttributeError
    
        def __setattr__(self, name, value):
            if name in col_mapping:
                self.handle.write(**{col_mapping[name]:value})
            else:
                object.__setattr__(self, name, value)
    
        def write(self, **kwargs):
            self.handle.write(**kwargs)
    
    class subClass_1(BaseClass):
        col_mapping = {
            'property1a':'columnX',
            'property1b':'columnY'
        }
    
        def __init__(self):
            self.handle = db_connector("table1")
    
        def some_bespoke_function():
            pass
    
    class subClass_2(BaseClass):
        col_mapping = {
            'property2a':'columnZ'
        }
        def __init__(self):
            self.handle = db_connector("table2")
    
        def another_bespoke_function():
            pass
    

    【讨论】:

      猜你喜欢
      • 2017-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多