staticmethod和classmethod的参数区别
看一段代码,引用知乎的一个回答
class Kls(object):
def __init__(self, data):
self.data = data
def printd(self):
print(self.data)
@staticmethod
def smethod(*arg):
print('Static:', arg)
@classmethod
def cmethod(*arg):
print('Class:', arg)
ik=Kls(23)
ik.printd()
ik.smethod("hi")
ik.cmethod("hi")
#Kls.printd() 该调用错误
Kls.smethod("hi")
Kls.cmethod("hi")
控制台输出:
23
23
Static: ('hi',)
Class: (<class '__main__.Kls'>, 'hi')
Static: ('hi',)
Class: (<class '__main__.Kls'>, 'hi')
解释一下它的运行:
首先我们在kls类中定义了我们常见的实例方法init(self, data)和printd(self)
作为一个实例方法,我们不免要带入第一个实例参数self
然而这里我们关注接下来的类函数以及静态函数,通过随后的函数调用以及输出我们可以很自然的发现:
静态方法不绑定任何参数
类方法自动绑定 类 作为第一个参数
另外注意成员函数只能用实例调用(注释所示代码错误),而类方法和静态方法类和对象都可以调用
staticmethod和classmethod的用处区别
刚才我讲了一个staticmethod和classmethod的语法区别,事实上这两者确实相差甚微,在具体使用上我们都知道这两者一般都是区别于成员函数而作为一个与实例无关的函数调用。然而我接下来也想讲述一下这两者在具体使用上的区别。
这里我参考并引用了stackoverflow上的回答,翻译并表达一下自己的理解
假设我们已有一个Date类
class Date(object):
def __init__(self, day=0, month=0, year=0):
self.day = day
self.month = month
self.year = year
关于classmethod
然而现在我们想加入一个根据形如’11-09-2012’的字符串去创建一个该类的对象的方法
很显然这个方法是跟具体实例无关的,我这里建议把它声明为类函数,像这样:
@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')
让我们仔细看看通过上面的实现我们得到了哪几种好处:
- 我们在类内定义实现了该函数并且现在我们能重用它。
- 在这里我们进行了一次好的封装(如果你认为在别处也可以实现一个这样独立的函数的话,这样就不能追求OOP原则)
- cls是类本身的一个对象而非任何一个实例,如果我们继承这个类,那么所有的子类也会自然定义了这个方法
关于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')
以上是我参考资料的一些自我补充理解,如有错误有望指正。