@classmethod与抽象基类

时间:2012-03-05 14:21:02

标签: python inheritance abstract-class

我有一个抽象基类和子类定义如下(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

2 个答案:

答案 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)