原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