Message 403578 - Python tracker (original) (raw)
@Terry I think the problem boils down to the fact that @classmethod @property decorated methods end up not being real properties.
Calling MyBaseClass.__dict__ reveals:
mappingproxy({'__module__': '__main__',
'expensive_class_property': <classmethod at 0x7f893e95dd60>,
'expensive_instance_property': <property at 0x7f893e8a5860>,
'__dict__': <attribute '__dict__' of 'MyBaseClass' objects>,
'__weakref__': <attribute '__weakref__' of 'MyBaseClass' objects>,
'__doc__': None,
'__abstractmethods__': frozenset(),
'_abc_impl': <_abc._abc_data at 0x7f893fb98740>})Two main issues:
- Any analytics or documentation tool that has special treatment for properties may not identify 'expensive_class_property' as a property if they simply check via
isinstance(func, property). Of course, this could be fixed by the tool-makers by doing a conditional check:
isinstance(func, property) or (`isinstance(func, classmethod)` and `isinstance(func.__func__, property)`expensive_class_propertydoes not implementgetter,setter,deleter. This seems to be the real dealbreaker, for example, if we do
MyBaseClass.expensive_class_property = 2
MyBaseClass().expensive_instance_property = 2Then the first line erroneously executes, such that MyBaseClass.dict['expensive_class_property'] is now int instead of classmethod, while the second line correctly raises AttributeError: can't set attribute since the setter method is not implemented.