我有一个抽象基类和子类定义如下(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)
这很好用,这意味着基类_DbObject
无法实例化,因为它只有属性getter方法的抽象版本。
try:
dbObject = _DbObject()
print "dbObject.ObjectType: " + dbObject.ObjectType
except Exception, err:
print 'ERROR:', str(err)
现在我能做到:
entry = Entry()
print entry.ObjectType
访问ObjectType
属性。但是,我希望能够做到的只是:
print Entry.ObjectType
但是,无论我在哪里尝试插入@classmethod
,我都会收到错误classmethod object is not callabale
。
答案 0 :(得分:1)
问题不在于你的ABC
,而是一个简单的事实,即在python中没有classproperty
这样的东西,你必须自己创建它。实际上有一个很好的question + answer on SO。实际上,将它与ABC一起使用也没有问题。
答案 1 :(得分:1)
因此,“属性”在Python中的工作方式的魔力是使用描述符协议 - 属性本身实现的,如果一个强大的内置提供了一个适用于实例的描述符,而不是你所见过的类。
所以,你需要一个“类属性” - 内置的属性不能给你,但描述符协议可以。描述符协议所说的是,无论何时从类中检索属性,如果它是具有__get__
方法的对象,则使用“self,instance,owner”调用该方法 - 如果从类中检索到该方法而不是来自实例,“instance”参数是None -
顺便说一句,正如@Constantinius所说,这与ABC完全没有关系,只是想要一个“类属性”。
class classproperty(object):
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
return self.func(owner)
class Entry(_DbObject):
_objectTypeID = 'ENTRY'
def _GetObjectType(cls):
return MyDatabaseModule.DoesSomethingWith(cls._objectTypeID)
ObjectType = classproperty(_GetObjectType, None)