定义在类中的代码块叫方法,Python的方法分为『实例方法』、『类方法』、『静态方法』,按照从前到后的顺序它们和实例对象的依赖程度依次降低。

我们先来看一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Date:
# 构造函数
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day

def tomorrow(self):
self.day += 1


def __str__(self):
return "{year}/{month}/{day}".format(year=self.year, month=self.month, day=self.day)


if __name__ == '__main__':
new_day = Date(2018, 12, 13)
new_day.tomorrow() # 调用这个对象的tomorrow方法
print(new_day)

# 输出结果:
2018/12/14

上面所定义的方法我们就称为实例方法。实例方法就是第一个参数必须是实例对象,该参数名一般约定为“self”,通过它来传递实例的属性和方法(也可以传类的属性和方法)而且只能由实例对象调用。

现在我们有这样一个场景:假设我们这里有2018-08-08这个字符串,我们要把它当做参数传递给我们的Date,然后进行返回时间。首先我们必需要对其进行格式化处理,这是一般的思维方式:

1
2
3
4
5
6
7
date_str = "2018-08-08"
year, month, day = tuple(date_str.split("-"))
new_str = Date(int(year), int(month), int(day))
print(new_str)

# 输出结果:
2018/8/8

不过这样做就有一个问题,就是我们每次都需要把它进行格式化的时候就需要加上上面的这段代码,为了提高代码的复用性,我们可以将其拿到我们的类内部,定义一个静态方法:

1
2
3
4
5
6
7
8
@staticmethod
def parse_date(date_str):
year, month, day = tuple(date_str.split("-"))
return Date(int(year), int(month), int(day))


# 输出结果:
2018/8/8

静态方法就是使用装饰器@staticmethod的方法,参数可以随意,没有“self”和“cls”参数,但是方法体中不能使用类或实例的任何属性和方法;实例对象和类对象都可以调用静态方法。

静态方法还有一个非常不好的地方就是刚才return语句里面的Data必须和我们的类名保持一致,而且一个被修改,另一个也必须要修改(硬编码的方式)。如果有一种可以自己随着我们类名而修改的方法就好了,类方法就可以做到这一点:

1
2
3
4
5
6
7
8
@classmethod
def from_str(cls, date_str):
year, month, day = tuple(date_str.split("-"))
return cls(int(year), int(month), int(day))


# 输出结果:
2018/8/8

类方法就是使用装饰器@classmethod,第一个参数必须是当前类对象,该参数名一般约定为“cls”(也就是说你是可以自定义的),通过它来传递类的属性和方法(不能传实例的属性和方法);实例对象和类对象都可以调用类方法。

[ - ]参考文章:
Python 实例方法、类方法、静态方法的区别与作用
python类的实例方法、静态方法和类方法区别及其应用场景
一个例子彻底理解Python的三种方法