I have posted a similar question before but I interpreted my problem wrong, so I flagged it for deletion and come forth with the new and correct problem.
My general goal is the following: I want to have a property
on a class, so I implement it on a metaclass using a property as suggested on my question Implementing a class property that preserves the docstring. Additionally, I want users to be able to subclass the base class and override this property with static values. The thing here is that if the user does not provide an attribute, I want to calculate a sensible default and since all configuration is done at the class level, I need a property at the class level.
A basic example will show this:
class Meta(type):
@property
def test(self):
return "Meta"
class Test(object):
__metaclass__ = Meta
class TestSub(Test):
test = "TestSub"
class TestSubWithout(Test):
pass
print(TestSub.test, TestSubWithout.test)
Here is what it prints:
('Meta', 'Meta')
And what I want it to print:
('TestSub', 'Meta')
Essentially, on TestSub
the user overrides the test
attribute himself. Now, TestSub
is the correct output, since the user provided it. In the case of TestSubWithout
, the user instead did not provide the attribute and so the default should be calculated (of course, the real calculation has more than just a static return, this is just to show it).
I know what happens here: First the attribute test
is assigned to TestSub
and then the metaclass overrides it. But I don't know how to prevent it in a clean and pythonic way.