I've been trying to see whether one can create an abstract class property by mixing the three decorators (in Python 3.9.6, if that matters), and I noticed some strange behaviour.
Consider the following code:
from abc import ABC, abstractmethodclass Foo(ABC):@classmethod@property@abstractmethoddef x(cls):print(cls)return Noneclass Bar(Foo):@classmethod@propertydef x(cls):print("this is executed")return super().x
This outputs
this is executed
<class '__main__.Bar'>
This means that somehow, Bar.x
ends up being called.
PyCharm warns me that Property 'self' cannot be deleted
. If I reverse the order of @classmethod
and @property
, Bar.x
is not called, but I still get the same warning, and also another one: This decorator will not receive a callable it may expect; the built-in decorator returns a special object
(this also appears whenever I put @property
above @classmethod
).
Removing any of the three decorators (with the appropriate changes: adding ()
when removing @property
or changing cls
to self
when removing @classmethod
) also prevents Bar.x
from being called.
I suppose all of this means that it's probably just a bad idea to directly mix those decorators (as indicated by discussion about class properties in other threads here).
Neverthless, I am curious: what is happening here? Why is Bar.x called?