原blog鏈接:如何讓classmethod只允許使用用類對象來調用
我們知道在python中使用classmethod可以把一個方法處理爲類方法,這樣就可以直接使用類對象來調用它了。但是,它也有一個不算問題的問題,就是也可以使用實例來調用,比如:
class A(object):
@classmethod
def p(cls):
print 'call p()'
a = A()
A.p()
a.p()
但是有時,我們可能希望這個方法只能被類對象來調用,而不能使用實例來調用。爲什麼會有這樣的需求?舉一個例子,數據庫操作中,Model有delete()和remove()方法。其中delete()是用在實例上的,刪除一個記錄,而remove()是定義爲classmethod的,刪除整個表的所有記錄。但是有時在實例上誤寫爲record.remove(),這樣的結果是會將表全部刪除,而不是隻刪除這一條記錄。所以這裏remove()具有一定的危險性。所以我想有這麼一種限制,即類方法只能用類對象來調用。當然,並不是所有的類方法都需要這樣,只對有破壞性或危險性的方法這樣處理。那麼怎麼做呢?可以通過寫了一個descriptor的類,可以幹這件事,同時它可以像classmethod一樣作爲decorator來使用。代碼如下:class classonlymethod(object):
"""
Use to limit the class method can only be called via class object, but not instance
object
>>> class A(object):
... @classonlymethod
... def p(cls):
... print 'call p()'
>>> A.p()
call p()
>>> a = A()
>>> try:
... a.p()
... except Exception as e:
... print e
Method p can only be called with class object
"""
def __init__(self, func):
self._func = func
def __get__(self, model_instance, model_class):
if model_instance is not None:
raise AttributeError("This method can only be called with class object.")
return super(classonlymethod, self).__get__(model_instance, model_class)
它使用了descriptor的特性,能過定義 __get__ 方法來區分類對象調用還是實例對象調用。
關於descriptor,可以參考:http://docs.python.org/2/howto/descriptor.html