class A(object):
def m1(self):
print("实例方法")
@classmethod
def m2(cls,n):
print('class method', n)
@staticmethod
def m3(m):
print('static method', n)
调用:
类方法和静态方法都用可以通过类名和实例名调用,因此可以在普通实例方法中使用self.m2(n)
self.m3(n)
来调用.
【区别】
class method与class绑定,static method与类和实例都没有绑定关系
>>>a=A()
>>>print(A.m2)
>>>print(a.m2)
>>>print(A.m3)
>>>print(a.m3)
<bound method A.m2 of <class '__main__.A'>>
<bound method A.m2 of <class '__main__.A'>>
<function A.m3 at 0x111e97200>
<function A.m3 at 0x111e97200>
应用场景
- 静态方法 static method
如果在方法中不需要访问任何实例方法和属性,纯粹地通过传入参数并返回数据的功能性方法,那么它就适合用静态方法来定义,它节省了实例化对象的开销成本,往往这种方法放在类外面的模块层作为一个函数存在也是没问题的,而放在类中,仅为这个类服务。
例如下面是微信公众号开发中验证微信签名的一个例子,它没有引用任何类或者实例相关的属性和方法。
from hashlib import sha1
import tornado.web
class SignatureHandler(tornado.web.RequestHandler):
def get(self):
"""
根据签名判断请求是否来自微信
"""
signature = self.get_query_argument("signature", None)
echostr = self.get_query_argument("echostr", None)
timestamp = self.get_query_argument("timestamp", None)
nonce = self.get_query_argument("nonce", None)
if self._check_sign(TOKEN, timestamp, nonce, signature):
logger.info("微信签名校验成功")
self.write(echostr)
else:
self.write("你不是微信发过来的请求")
@staticmethod
def _check_sign(token, timestamp, nonce, signature):
sign = [token, timestamp, nonce]
sign.sort()
sign = "".join(sign)
sign = sha1(sign).hexdigest()
return sign == signature
- 类方法 class method
作为工厂方法创建实例对象,例如内置模块 datetime.date 类中就有大量使用类方法作为工厂方法,以此来创建date对象。
class date:
def __new__(cls, year, month=None, day=None):
self = object.__new__(cls)
self._year = year
self._month = month
self._day = day
return self
@classmethod
def fromtimestamp(cls, t):
y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
return cls(y, m, d)
@classmethod
def today(cls):
t = _time.time()
return cls.fromtimestamp(t)
如果希望在方法裡面调用静态类,那么把方法定义成类方法是合适的,因为要是定义成静态方法,那么你就要显示地引用类A,这对继承来说可不是一件好事情。
class A:
@staticmethod
def m1()
pass
@staticmethod
def m2():
A.m1() # bad
@classmethod
def m3(cls):
cls.m1() # good