2012-03-05 114 views
2

我有一個抽象基類和(Python 2.7版)中所定義如下子類:@classmethod與抽象基類

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

回答

1

問題不在於你的ABC,而是一個簡單的事實,即在python中沒有像classproperty這樣的東西,你必須自己創建它。其實有一個很好的question + answer on SO。實際上,在您的ABC中使用它也不會有問題。

1

所以,對於這樣「屬性」魔術在Python使用作品的描述符協議實現 - 屬性本身,如果一個強大的內置,可提供對於實例行之有效的描述符,而不是類如你所看見的。

所以,你需要一個「類屬性」 - 屬性內置的不能給你,但描述協議即可。什麼描述協議說的是,每當一個屬性是從類檢索,如果它是一個__get__方法的對象,該方法被稱爲與「自我,實例所有者」 - 如果是從類檢索,而不是從一個實例,你的「實例」參數是無-

順便說一句,如@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)