咱们在类中定义的方法都是对象方法,也就是说这些方法都是发送给对象的消息。实际上,咱们写在类中的方法并不须要都是对象方法,例如咱们定义一个“三角形”类,经过传入三条边长来构造三角形,并提供计算周长和面积的方法,可是传入的三条边长未必能构造出三角形对象,所以咱们能够先写一个方法来验证三条边长是否能够构成三角形,这个方法很显然就不是对象方法,由于在调用这个方法时三角形对象还没有建立出来(由于都不知道三条边能不能构成三角形),因此这个方法是属于三角形类而并不属于三角形对象的。咱们可使用静态方法来解决这类问题,代码以下所示。java
from math import sqrt class Triangle(object): def __init__(self, a, b, c): self._a = a self._b = b self._c = c @staticmethod def is_valid(a, b, c): return a + b > c and b + c > a and a + c > b def perimeter(self): return self._a + self._b + self._c def area(self): half = self.perimeter() / 2 return sqrt(half * (half - self._a) * (half - self._b) * (half - self._c)) def main(): a, b, c = 3, 4, 5 # 静态方法和类方法都是经过给类发消息来调用的 if Triangle.is_valid(a, b, c): t = Triangle(a, b, c) print(t.perimeter()) # 也能够经过给类发消息来调用对象方法可是要传入接收消息的对象做为参数 # print(Triangle.perimeter(t)) print(t.area()) # print(Triangle.area(t)) else: print('没法构成三角形.') if __name__ == '__main__': main()
和静态方法比较相似,Python还能够在类中定义类方法,类方法的第一个参数约定名为cls,它表明的是当前类相关的信息的对象(类自己也是一个对象,有的地方也称之为类的元数据对象),经过这个参数咱们能够获取和类相关的信息而且能够建立出类的对象,代码以下所示。python
from time import time, localtime, sleep class Clock(object): """数字时钟""" def __init__(self, hour=0, minute=0, second=0): self._hour = hour self._minute = minute self._second = second @classmethod def now(cls): ctime = localtime(time()) return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec) def run(self): """走字""" self._second += 1 if self._second == 60: self._second = 0 self._minute += 1 if self._minute == 60: self._minute = 0 self._hour += 1 if self._hour == 24: self._hour = 0 def show(self): """显示时间""" return '%02d:%02d:%02d' % \ (self._hour, self._minute, self._second) def main(): # 经过类方法建立对象并获取系统时间 clock = Clock.now() while True: print(clock.show()) sleep(1) clock.run() if __name__ == '__main__': main()
因为python类中只能有一个初始化方法,不能按照不一样的状况初始化类。
参考django https://docs.djangoproject.com/en/1.9/ref/models/instances/ 请看下面的代码。django
# coding:utf-8 class Book(object): def __init__(self, title): self.title = title @classmethod def create(cls, title): book = cls(title=title) return book book1 = Book("python") book2 = Book.create("python and django") print(book1.title) print(book2.title)
特别说明,静态方法也能够实现上面功能,当静态方法每次都要写上类的名字,不方便。函数
下面的代码,静态方法调用另外一个静态方法,若是改用类方法调用静态方法,可让cls代替类,
让代码看起来精简一些。也防止类名修改了,不用在类定义中修改原来的类名。code
# coding:utf-8 class Foo(object): X = 1 Y = 2 @staticmethod def averag(*mixes): return sum(mixes) / len(mixes) @staticmethod def static_method(): return Foo.averag(Foo.X, Foo.Y) @classmethod def class_method(cls): return cls.averag(cls.X, cls.Y) foo = Foo() print(foo.static_method()) print(foo.class_method())
从下面代码能够看出,若是子类继承父类的方法,子类覆盖了父类的静态方法,
子类的实例继承了父类的static_method静态方法,调用该方法,仍是调用的父类的方法和类属性。
子类的实例继承了父类的class_method类方法,调用该方法,调用的是子类的方法和子类的类属性。对象
# coding:utf-8 class Foo(object): X = 1 Y = 2 @staticmethod def averag(*mixes): return sum(mixes) / len(mixes) @staticmethod def static_method(): return Foo.averag(Foo.X, Foo.Y) @classmethod def class_method(cls): return cls.averag(cls.X, cls.Y) class Son(Foo): X = 3 Y = 5 @staticmethod def averag(*mixes): return sum(mixes) / 3 p = Son() print(p.static_method()) print(p.class_method()) # 1.5 # 2.6666666666666665