python - 继承setter,覆盖python抽象类中的getter

标签 python inheritance properties abc

假设您在基类中有一个属性,该属性具有一个 setter 方法,该方法将在所有子类中使用,但在所有子类中具有不同的 getter 方法。理想情况下,您只想在基类中为 setter 方法编写一次代码。此外,您希望将基类抽象化,因为它没有完整的 getter 方法。有什么办法吗?

天真地,我认为它应该是这样的:

class _mystring(object):

    __metaclass__ = abc.ABCMeta

    @abc.abstractproperty
    def str(self):
        pass

    @str.setter
    def str(self,value):
        self._str = value

class uppercase(_mystring):

    @_mystring.str.getter
    def str(self):
        return self._str.upper()

但是 upper = uppercase() 失败并返回 Can't instantiate abstract class uppercase with abstract methods str

如果我将 _mystring 类中的 @abc.abstractproperty 更改为 @property,则 upper = uppercase() 有效,但 upper = _mystring() 也有效,这是我不想要的。

我错过了什么?

谢谢!

最佳答案

我设法围绕 abstractproperty 做了一个小包装器来完成它:

class partialAP(abc.abstractproperty):
    def getter(self, func):
        if getattr(func, '__isabstractmethod__', False) or getattr(self.fset, '__isabstractmethod__', False):
            p = partialAP(func, self.fset)
        else:
            p = property(func, self.fset)
        return p

    def setter(self, func):
        if getattr(self.fget, '__isabstractmethod__', False) or getattr(func, '__isabstractmethod__', False):
            p = partialAP(self.fget, func)
        else:
            p = property(self.fset, func)
        return p

然后您的代码只需稍加修改即可工作:

class _mystring(object):

    __metaclass__ = abc.ABCMeta

    @partialAP
    @abc.abstractmethod
    def str(self):
        pass

    @str.setter
    def str(self,value):
        self._str = value

class uppercase(_mystring):

    @_mystring.str.getter
    def str(self):
        return self._str.upper()

然后行为如愿:

>>> _mystring()
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    _mystring()
TypeError: Can't instantiate abstract class _mystring with abstract methods str
>>> u = uppercase()
>>> u.str = 'a'
>>> u.str
'A'

我的 partialAP 包装器必须与 abc.abstractmethod 结合使用。你所做的是使用 abstractmethod 来装饰你想要抽象的属性(getter 或 setter)的“部分”,并使用 partialAP 作为第二个装饰器。 partialAP 定义了 getter/setter 函数,仅当 getter 和 setter 都是非抽象的时,才将属性替换为普通属性。

很明显,您必须稍微扩展一下才能使其对属性删除器也有值(value)。如果您有更复杂的继承层次结构,也可能存在无法正确处理的极端情况。

后代的旧解决方案:

class _mystring(object):

    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def _strGet(self):
        pass

    def _strSet(self,value):
        self._str = value

    str = property(_strGet, _strSet)

class uppercase(_mystring):

    def _strGet(self):
        return self._str.upper()
    str = _mystring.str.getter(_strGet)

然后就可以了:

>>> _mystring()
Traceback (most recent call last):
  File "<pyshell#39>", line 1, in <module>
    _mystring()
TypeError: Can't instantiate abstract class _mystring with abstract methods _strGet
>>> u = uppercase()
>>> u.str = 'a'
>>> u.str
'A'

诀窍是您不必使用方便的装饰器。 abstractproperty 装饰器将整个属性标记为抽象的。您需要做的是创建两个方法,一个抽象方法(用于 getter)和一个常规方法(用于 setter),然后创建一个组合它们的常规属性。然后,当您扩展该类时,您必须覆盖抽象 getter 并将其与基类属性显式“混合”(使用 _mystring.str.getter)。

不能使用 @_mystring.str.getter 的原因是装饰器强制 getter 和 setter 与属性本身同名。如果您只想将两者之一标记为抽象,则它们必须具有不同的名称,否则您无法单独获取它们。

请注意,此解决方案要求子类为其 getter 提供正确的名称(在本例中为 _strGet),以满足 ABC 他们已覆盖抽象方法的事实。

关于python - 继承setter,覆盖python抽象类中的getter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19715507/

相关文章:

c++ - 如何在虚拟继承下游使用参数化基类构造函数

python - 如何将字符串写入特定行号?

python - 如何在 python 2.x 和 3.x 中直接打印到文本文件?

java - Java 开发者视角下的 Django

python - 禁止向 Python 子类添加新方法

C++ 结构引用类型

python - 如何与Python-Mysql交互

java - 属性文件中的屏蔽

java - 有没有办法在 Apache PropertiesConfiguration 中使用占位符

c# - 如何在不使用反射的情况下创建通用属性访问器?