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

Darren Dale dsdale24 at gmail.com
Fri Mar 18 18:29:52 CET 2011


On Sun, Mar 13, 2011 at 12:49 PM, Darren Dale <dsdale24 at gmail.com> wrote:
> 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!:

The modifications to "property" to better support abstract base
classes using the decorator syntax and @abstractmethod (rather than
@abstractproperty) are even simpler than I originally thought:

class Property(property):

    def __init__(self, *args, **kwargs):
        super(Property, self).__init__(*args, **kwargs)
        for f in (self.fget, self.fset, self.fdel):
            if getattr(f, '__isabstractmethod__', False):
                self.__isabstractmethod__ = True
                break

>
> 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())
>

running this example yields:

Can't instantiate abstract class C with abstract methods x
Can't instantiate abstract class D with abstract methods x
<__main__.E object at 0x212ee10>

Wouldn't it be possible to include this in python-3.3?

Darren



More information about the Python-ideas mailing list