对于一般的计算机语言,都会提供静态方法,这个方法可以认为是类的方法。即可以直接 类.方法(),也可以通过类的实例,也就是对象.方法()进行调用。就静态方法这方面来说,python语言和其他提供了静态方法的语言来说并没什么区别。
比如在java中,main方法(主函数)就是一个静态方法。
class Test
{
public static void main(String[] args)
{
//code
}
}
而在python中则采用装饰器的形式(python中并没有主函数的概念),即@staticmethod。
class Test(object):
@staicmethod
def main():
pass
以上两者虽然在形式上有所不同,但是在使用上是一样的。
扩展阅读:装饰器
从字面上来看,classmethod的意思是类方法,看起来和staticmethod类似,但其实不然,不过它们还是有相似之处的。
相似之处:
除了上面提到的之外,它们两个的用法则是南辕北辙。比如,classmethod的第一个参数cls来表示类(默认情况)。
接下来,以一个具体的场景来说明。
假设要使用python3自己开发一个ORM(Object Relate Mapping,对象关系映射)。
数据库中有一个user表, 主键是uid,其他的还有name 名字、password 密码。那么在程序中使用时就需要查表来获取对应的数据,并把一列数据封装成一个对象。也就是说,程序需要一个从数据库的数据到python对象的映射,这个映射就叫做ORM。
本篇不打算具体讲解是如何映射的,想要具体了解的可以点这里。
假设你已经把基础的工作都做好了,那么此时的UML图如下所示:
即Model继承自dict,并提供了一些通用的函数。比如find()方法,就是根据主键查表获取满足条件的数据。
对于python来说,这个方法是可以放在Model中的,那就是使用到classmethod装饰器:
class Model(dict, metaclass=ModelMetaclass):
#...
@classmethod
def find(cls, pk):
"""find object by primary key"""
sql = '%s where `%s`=?' % (cls.__select__, cls.__primary_key__)
rs = db.select_one(sql, pk)
if rs is None:
return None
return cls(**rs)
上面的代码比较简单,功能就是根据主键来进行查表,如果找到对应的数据项(db.select_one返回的是dict或者None),则调用cls的构造方法来创建cls类的一个实例。
如果不使用classmethod而是使用staticmethod的话,就只能把上面的方法稍微修改后放到User当中。
class User(Model):
#...
@staticmethod
def find(pk):
"""find object by primary key"""
sql = '%s where `%s`=?' % (User.__select__, User.__primary_key__)
rs = db.select_one(sql, pk)
if rs is None:
return None
return User(**rs)
综合比较上面的代码就可以发现,两者的代码基本一致,只不过由通用的cls转到了具体的User而已。
换句话说,在python3中,类本身也可以作为一个变量来传递。