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

Guido van Rossum guido at python.org
Fri Mar 18 19:36:01 CET 2011


On Fri, Mar 18, 2011 at 10:29 AM, Darren Dale <dsdale24 at gmail.com> wrote:
> 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?

Sounds good to me.

-- 
--Guido van Rossum (python.org/~guido)



More information about the Python-ideas mailing list