5

According to the docs it should work to combine @property and @abc.abstractmethod so the following should work in python3.3:

import abc

class FooBase(metaclass=abc.ABCMeta):

    @property
    @abc.abstractmethod
    def greet(self):
        """ must be implemented in order to instantiate """
        pass

    @property
    def greet_comparison(self):
        """ must be implemented in order to instantiate """
        return 'hello'

class Foo(FooBase):
    def greet(self):
        return 'hello'

test the implementation:

In [6]: foo = Foo()
In [7]: foo.greet
Out[7]: <bound method Foo.greet of <__main__.Foo object at 0x7f935a971f10>>

In [8]: foo.greet()
Out[8]: 'hello'

so it is obviously not a property, because then it should work like that:

In [9]: foo.greet_comparison
Out[9]: 'hello'

Maybe I'm to stupid or it simply doesn't work, somebody has an idea?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
mortbauer
  • 325
  • 5
  • 11

1 Answers1

8

If you want greet to be a property, you still need to use the @property decorator in your implementation:

class Foo(FooBase):
    @property
    def greet(self):
        return 'hello'

All that an ABC metaclass does is test wether or not you have provided the same name in the concrete class; it doesn't care if it is a method or a property or a regular attribute.

Because it doesn't care, it doesn't magically apply property decorators either. This is a good thing; perhaps in a specific implementation a static attribute is enough to satisfy the requirement, and a property would be overkill.

The purpose of a ABC metaclass is to help you detect gaps in your implementation; it never was intended to enforce the types of the attributes.

Note that before Python 3.3 you can not combine a @property with an @abstractmethod. You would have to use an @abstractproperty decorator instead. There is an ambiguity there when your property needs more than a simple getter in that case; Python 3.3 covers that case much better (see issue 11610 for the painful details).

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • If you were to have an abstract setter, would decorating greet fulfill the override requirement? Just a point of interest. – m.brindley Feb 03 '13 at 09:40
  • @m.brindley: if `greet in dir(Foo)` works, it satisfies as an override. See this [previous answer of mine](http://stackoverflow.com/questions/14441619/actual-difference-in-implementing-overriding-using-abstractproperty-and-abstra/14441682#14441682) on how ABC checks for overrides. – Martijn Pieters Feb 03 '13 at 09:41
  • Thanks for the explanation, one small thing on your last sentence, i i used it because the [python3.3 docs](http://docs.python.org/dev/whatsnew/3.3.html#improved-modules) mention, that the `@abstractproperty` decorator is deprecticated. – mortbauer Feb 03 '13 at 11:02
  • Ah, I had not seen that yet; thanks for pointing that out! It does make sense; by supporting property methods like that an ambiguity (that I was not aware of) is resolved very nicely! – Martijn Pieters Feb 03 '13 at 11:17
  • newer versions of python deprecate the `abstractproperty` decorator again. now one just needs to use `property` and `abstractmethod` together, and the order seems to matter – Will Gu Aug 20 '20 at 17:19