[Python-ideas] Would it possible to define abstract read/write properties with decorators?

Darren Dale dsdale24 at gmail.com
Sun Mar 13 17:49:28 CET 2011


On Sun, Mar 13, 2011 at 11:18 AM, Darren Dale <dsdale24 at gmail.com> wrote:
[...]
> It seems like it should be possible for Python to support the
> decorator syntax for declaring abstract read/write properties. The
> most elegant approach might be the following, if it could be
> supported:
>
> class Foo(metaclass=ABCMeta):
>    # Note the use of @property rather than @abstractproperty:
>    @property
>    @abstractmethod
>    def bar(self):
>        return 1
>    @bar.setter
>    @abstractmethod
>    def bar(self, val):
>        pass
>
> I thought that would work with Python-3.2, but Foo is instantiable
> even though there are abstractmethods. If python's property could be
> tweaked to recognize those abstract methods and raise the usual
> TypeError, then we could subclass the abstract base class Foo in the
> usual way:

Here is a working example!:

import abc

class Property(object):

    def __init__(self, getter, setter=None):
        self._getter = getter
        self._setter = setter
        if (getattr(getter, '__isabstractmethod__', False) or
                getattr(setter, '__isabstractmethod__', False)):
            self.__isabstractmethod__ = True

    def __get__(self, instance, owner):
        if instance is None:
            return self
        return self._getter(instance)

    def __set__(self, instance, value):
        return self._setter(instance, value)

    def getter(self, func):
        return Property(func, self._setter)

    def setter(self, func):
        return Property(self._getter, func)

class C(metaclass=abc.ABCMeta):
    @Property
    @abc.abstractmethod
    def x(self):
        return 1
    @x.setter
    @abc.abstractmethod
    def x(self, val):
        pass

try:
    c=C()
except TypeError as e:
    print(e)

class D(C):
    @C.x.getter
    def x(self):
        return 2

try:
    d=D()
except TypeError as e:
    print(e)

class E(D):
    @D.x.setter
    def x(self, val):
        pass

print(E())



More information about the Python-ideas mailing list