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

Darren Dale dsdale24 at gmail.com
Sun Mar 13 16:18:00 CET 2011


I'm a big fan of the decorator syntax introduced in python-2.6 to
define properties:

class Foo(object):
    @property
    def bar(self):
        return 1
    @bar.setter
    def bar(self, val):
        pass

Lately I've been learning about ABCs at
http://www.python.org/dev/peps/pep-3119/ and
http://docs.python.org/py3k/library/abc.html . The documentation
states that abstract read-only properties can be defined with the
decorator syntax, but the "long-form" [bar=property(getbar, setbar)]
property declaration is required for read/write properties. Would it
be possible to support the decorator syntax for read/write properties
in python-3.3? In python-3.2, this is valid code that (sort-of)
produces an abstract read/write property:

class Foo(metaclass=ABCMeta):
    @abstractproperty
    def bar(self):
        return 1
    @bar.setter
    def bar(self, val):
        pass

but subclasses of Foo can be instantiated even if they do not define a
bar.setter:

class Baz(Foo):
     @property
     def bar(self):
         return 1
baz=Baz()

which must have been the reason for requiring the long-form property
declaration syntax.

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:

class Baz(Foo):
    @Foo.bar.getter
    def bar(self):
        return 2

this is not yet instantiable, Baz.bar.setter is still abstract...

    @bar.setter
    def bar(self, val):
        pass

Now Baz could be instantiated.

Is this feasible?

Darren



More information about the Python-ideas mailing list