Python 在超类中使用描述符以避免子类中的代码重复

Python 在超类中使用描述符以避免子类中的代码重复,python,python-decorators,python-descriptors,Python,Python Decorators,Python Descriptors,在python中,我有一个基类,从中派生了一组子类。每个子类都有一些特定于子类的函数和一些独特的属性,这些属性具有使用@property装饰器定义的getter和setter。但是如果我有很多属性,就会导致大量代码重复,因为getter和setter都有相同的形式。以下是一个粗略的示例草图,以数据库访问为例: class BaseClass(): def __init__(self): self.handle = None def write(self, **k

在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

有没有办法在基类中定义一些东西,以避免编写所有那些
@property
装饰器?理想情况下,我会在子类中定义一些东西,比如子类_1的
self.mapping={'property1a':'columnX','property1a':'columnX'}
,子类_2的
self.mapping={'property2a':'columnZ'}
,回答我自己的问题:解决方案似乎是在基类中使用
\uu getattr\uuuuuu
(我没有意识到)只有在属性不存在时才会调用。因此(奇怪的是)这里的关键是根本不定义属性,而是捕获对这些不存在的“属性”的读写调用,并根据需要启动函数。根本不需要装饰器:

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