rank | vote | view | answer | url |
---|---|---|---|---|
66 | 1321 | 508348 | 11 | url |
虽然 classmethod
和 staticmethod
非常接近, 但是用途却是不同: classmethod
必须把类对象的引用作为第一个参数,而 staticmethod
则不需要.
class Date(object):
def __init__(self, day=0, month=0, year=0):
self.day = day
self.month = month
self.year = year
@classmethod
def from_string(cls, date_as_string):
day, month, year = map(int, date_as_string.split('-'))
date1 = cls(day, month, year)
return date1
@staticmethod
def is_date_valid(date_as_string):
day, month, year = map(int, date_as_string.split('-'))
return day <= 31 and month <= 12 and year <= 3999
date2 = Date.from_string('11-09-2012')
is_date = Date.is_date_valid('11-09-2012')
让我们来创建一个处理日期的 class:
class Date(object):
def __init__(self, day=0, month=0, year=0):
self.day = day
self.month = month
self.year = year
这个 class 很显然是用来存储特定日期的信息.
这里用 Python 的 __init__
来初始化类实例, 它可以接收参数作为一个 instancemethod
, 它的第一个参数 self
是新建实例的引用.
我们可以用 classmethod
来很好的完成一些功能.
假设我们想通过一些形如 dd-mm-yyyy
的 string 来创建 Date
实例.而且我们需要在我们工程里许多不同的地方实现.
所以我们必须:
- 解析 string 为天,月和年这3个整数或者3元元祖.
- 通过传递这些值来完成
Date
的初始化调用
day, month, year = map(int, string_date.split('-'))
date1 = Date(day, month, year)
在 C++ 里可以用 overloading 的方法来实现, 但是 Python 里没有 overloading.取而代之的我们可以使用 classmethod
.让我们来创建另一种 constructor
@classmethod
def from_string(cls, date_as_string):
day, month, year = map(int, date_as_string.split('-'))
date1 = cls(day, month, year)
return date1
date2 = Date.from_string('11-09-2012')
让我们仔细看看上面两个实现,来看看两个实现的优缺点:
- 我们在一个地方实现了 date string 的转换并且可以复用.
- 很好的封装(如果你认为或许可以实现一个函数来解析, 但是这么做更符合 OOP 设计)
cls
是一个承载 class 自己的对象, 并不是 class 的实例.这个非常好用,因为只要我们继承了Data
class, 所有的子类都拥有from_string
这个方法.
staticmethods
呢?它非常像 classmethod
但是它不包含任何必须的参数(比如说类方法或者实例方法).
让我们看看下一个用法.
我们想验证一个 date string 的有效性,这个任务不需要绑定到实例上只需要绑定到类上面.
staticmethod
对我们来说就比较好用了.我们看看下一段代码:
@staticmethod
def is_date_valid(date_as_string):
day, month, year = map(int, date_as_string.split('-'))
return day <= 31 and month <= 12 and year <= 3999
# usage:
is_date = Date.is_date_valid('11-09-2012')
所以我们看到 staticmethod
就想一个函数一样不需要指定 class,语法上的调用也非常像函数,没办法访问对象及其内部,而 classmethod
就可以.