classmethod 与staticmethod区别
- 某个函数前面加上了staticmethod或者classmethod的话,那么这个函数就可以不通过实例化直接调用。
- 什么意思呢?就是说有时候,我们需要把一些具有特定功能的函数放到一起,做成包导入Python程序,最好就是把他们放到一个类中,但是一个类每次我都要去实例化他,我觉得很麻烦,于是我在函数前面加上了@staticmethod,@classmethod,那么我下次用这个函数的功能的时候,可以直接用 类名.函数名的形式了。
区别
- @staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。
- @classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。
- 如果在@staticmethod中要调用到这个类的一些属性方法,只能直接类名.属性名或类名.方法名。
- 而@classmethod因为持有cls参数,可以来调用类的属性,类的方法,实例化对象等,避免硬编码。
简单来说,就是staticmethod不需要传入表示自身对象参数,而classmethod需要传入一个类似于self的cls参数。那么既然classmethod麻烦一点,必然有他麻烦的道理,就是:使用classmethod的话,凡是在该类中的类的属性,方法,实例化对象等,都可以调用出来。
定义类方法的几种方式:
- 常规方式 : 需要self隐士传递当前类对象的实例。
- @classmethod 装饰器修饰 :需要通过cls参数传递当前类对象
- @staticmethod 装饰器修饰 :与普通函数是一样
class A(object):
def foo(self, x):
print("executing foo(%s, %s)" % (self, x))
@classmethod
def class_foo(cls, x):
print("executing class_foo(%s, %s)" % (cls, x))
@staticmethod
def static_foo(x):
print("executing static_foo(%s)" % x)a = A()
调用说明
#类中方法均可通过:对象实例.方法() 访问
a.foo(1) #executing foo(<__main__.A object at 0x0000000001E9B488>, 1)
a.class_foo(2) #executing class_foo(<class '__main__.A'>, 2)
a.static_foo(3) #executing static_foo(3)
#@classmethod修饰方法调用: 类对象或对象实例调用
A.class_foo(4) #executing class_foo(<class '__main__.A'>, 4)
a.class_foo(5) #executing class_foo(<class '__main__.A'>, 5)
# 通过类对象 访问常规方法即没有修饰符的方法
A.foo(a,6) #executing foo(<__main__.A object at 0x000000000284C488>, 6)
其他案例:
class A(object):
def __init__(self,name):
self.name = name
def foo(self, x):
print("executing foo(%s, %s, %s)" % (self, x,self.name))
@classmethod
def class_foo(cls, x):
print("executing class_foo(%s, %s)" % (cls, x))
# 返回一个实例对象
return cls(x)
@staticmethod
def static_foo(x):
print("executing static_foo(%s)" % x)
dd = A.class_foo(2) # executing class_foo(<class '__main__.A'>, 2)
print(dd.name) # 2
dd.foo(3) # executing foo(<__main__.A object at 0x0000000001E8B708>, 3, 2)
class CeShi:
name = '测试'
def __init__(self,x,y):
self.x = x
self.y = y
@property #在CeShi_add函数前加上@property,使得该函数可直接调用,封装起来
def CeShi_add(self):
return self.x + self.y
#在CeShi_info函数前加上@classmethon,则该函数变为类方法,
@classmethod #该函数只能访问到类的数据属性,不能获取实例的数据属性
def CeShi_info(cls): #python自动传入位置参数cls就是类本身
print('这是一个%s'%cls.name) #cls.CeShi_name调用类自己的数据属性
CeShi.CeShi_info()