Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Question about abstract base classes and abstract properties -- Python 2.7

406 views
Skip to first unread message

Gerald Britton

unread,
Oct 22, 2016, 11:06:37 AM10/22/16
to
I was rereading the 2.7 docs about abstract base classes the other day. I
found this line in the usage section of the abc.abstractproperty function:

"This defines a read-only property; you can also define a read-write
abstract property using the ‘long’ form of property declaration:"

along with an example. so I copied the example and put in a little
surrounding code:


from abc import ABCMeta, abstractproperty

class C(object):
__metaclass__ = ABCMeta
def getx(self): pass
def setx(self, value): pass
x = abstractproperty(getx, setx)

class D(C):
@property
def x(self):self._x

d = D()
print(d)

When I ran this, I expected an exception, since I defined a read/write
abstract property but only implemented the read operation. However, the
example runs fine. That is the class D can be instantiated without error.
Of course I cannot set the property since I didn't implement that part.

Now, If I don't implement the property at all, I can' instantiate the
class. I get:

"TypeError: Can't instantiate abstract class D with abstract methods x"

which is what I would expect. What I don't understand is why I don't get a
similar error when I implement the read operation for the property but not
the write operation.

If this actually doesn't work (catching the non-implementation at
instantiation time), then why is it documented this way. To me at least
the doc implies that it *will* raise on the missing write property
implementation (otherwise, what's the point of the example?)

Is this a doc bug, an ABC bug or just me? (I've been known to be buggy
from time to time!)

--
Gerald Britton

Gerald Britton

unread,
Jan 10, 2017, 8:26:57 PM1/10/17
to
I was rereading the 2.7 docs about abstract base classes the other day. I
found this line in the usage section of the abc.abstractproperty function:

"This defines a read-only property; you can also define a read-write
abstract property using the ‘long’ form of property declaration:"

along with an example. so I copied the example and put in a little
surrounding code:


from abc import ABCMeta, abstractproperty

class C(object):
__metaclass__ = ABCMeta
def getx(self): pass
def setx(self, value): pass
x = abstractproperty(getx, setx)

class D(C):
@property
def x(self):self._x

d = D()
print(d)

When I ran this, I expected an exception, since I defined a read/write
abstract property but only implemented the read operation. However, the
example runs fine. That is the class D can be instantiated without error.
Of course I cannot set the property since I didn't implement that part.

Now, If I don't implement the property at all, I can't instantiate the
class. I get:

"TypeError: Can't instantiate abstract class D with abstract methods x"

which is what I would expect. What I don't understand is why I don't get a
similar error when I implement the read operation for the property but not
the write operation.

If this actually doesn't work (catching the non-implementation at
instantiation time), then would it be appropriate to amend the
documentation? To me at least the doc implies that it *will* raise on the
missing write property implementation (otherwise, what's the point of the
example?)

Or, am I just not grokking it properly?

Steven D'Aprano

unread,
Jan 10, 2017, 9:16:54 PM1/10/17
to
On Wednesday 11 January 2017 12:26, Gerald Britton wrote:

> I was rereading the 2.7 docs about abstract base classes the other day. I
> found this line in the usage section of the abc.abstractproperty function:
>
> "This defines a read-only property; you can also define a read-write
> abstract property using the ‘long’ form of property declaration:"
>
> along with an example. so I copied the example and put in a little
> surrounding code:
>
>
> from abc import ABCMeta, abstractproperty
>
> class C(object):
> __metaclass__ = ABCMeta
> def getx(self): pass
> def setx(self, value): pass
> x = abstractproperty(getx, setx)
>
> class D(C):
> @property
> def x(self):self._x
>
> d = D()
> print(d)
>
> When I ran this, I expected an exception, since I defined a read/write
> abstract property but only implemented the read operation.

I expected the same thing.


[...]
> If this actually doesn't work (catching the non-implementation at
> instantiation time), then would it be appropriate to amend the
> documentation? To me at least the doc implies that it *will* raise on the
> missing write property implementation (otherwise, what's the point of the
> example?)

Personally, I consider this a design bug: as designed, abstractproperty is
broken. But I couldn't call it a functional bug: it looks like it is working as
documented, as useless as that it.

Note that in Python 3.3 and better, abstractproperty is deprecated: the ABC
metaclass is smart enough to work with the regular property decorator:

https://docs.python.org/3.6/library/abc.html#abc.abstractproperty



> Or, am I just not grokking it properly?

No, I agree with you. I think that a bug request to improve the documentation
is appropriate.



--
Steven
"Ever since I learned about confirmation bias, I've been seeing
it everywhere." - Jon Ronson

0 new messages