I have an Abstract Base Class and subclasses defined as follows (Python 2.7):
import abc
import MyDatabaseModule
class _DbObject(object):
__metaclass__ = abc.ABCMeta
def _GetObjectType(self):
raise NotImplementedError, "Please override in the derived class"
ObjectType = abc.abstractproperty(_GetObjectType, None)
class Entry(_DbObject):
_objectTypeID = 'ENTRY'
def _GetObjectType(self):
return MyDatabaseModule.DoesSomethingWith(self._objectTypeID)
ObjectType = property(_GetObjectType, None)
This works fine, meaning that the base class _DbObject cannot be instantiated because it has only an abstract version of the property getter method.
try:
dbObject = _DbObject()
print "dbObject.ObjectType: " + dbObject.ObjectType
except Exception, err:
print 'ERROR:', str(err)
Now I can do:
entry = Entry()
print entry.ObjectType
to get access to the ObjectType property. However, what I would like to be able to do is just:
print Entry.ObjectType
However, wherever I try to insert @classmethod, I get the error classmethod object is not callabale.
So, the magic for the way “property” works in Python is implemented using the descriptor protocol – property itself if a powerful built-in that provides a descriptor that works well for instances, not classes as you had seen.
So, you need a “class property” – the
propertybuilt-in can’t give you that, but the descriptor protocol can. What the descriptor protocol says is that whenever an attribute is retrieved from the class, if it is an object with a__get__method, that method is called with “self, instance, owner” – and if it is retrieved from the class, instead of from an instance, the “instance” parameter is set toNone.BTW, as stated by @Constantinius, this does not have to do with the ABC’s at all, just with you wanting a “class property”.