1、#类方法@classmethod,只能访问类变量,不能访问实例变量,通过cls参数传递当前类对象,不需要实例化,直接【类名.方法名()】,可通过类对象和类对象实例访问
2、#静态方法@staticmethod,名义归类管,实际跟类没关系,跟类关联截断了,是类下单独的函数,可以不传递任何参数,不需要实例化,直接【类名.方法名(),可通过类对象和类对象实例访问
3、#实例方法,一般类下未带修饰符@是实例方法,需要实例化后调用
@property、@staticmethod和@classmethod应用与区分
在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以对属性随便修改,不能限制输入
class Student(object):
def __init__(self, name, age):
self.name = name
self.age = age
@property #引用装饰器property
def age(self):
return self.__age
@age.setter #函数修饰后可以作为装饰器使用调用后可以修改原始数据
def age(self,value):
if not isinstance(value, int):
raise ValueError('score must be an integer!') #非int类型抛异常
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!') #年龄基本都是0-100以内,限制输入
self.__age = value
s = Student('Mitsui', 24) #当age参数传入24,age会去找被property修饰的age 实际上age = self.__age而非self.age
print(s.name,s.age) #也就是age参数会传入age()方法中的value参数,开始执行age.setter,实现规范输入的目的,
s.age = 18 #同时在调用时,把 age()方法变成一个可以赋值的属性,让调用者更加方便的调用
s.name = 'BOBO'
print(s.name)
print(s.age) #没有赋值实际上执行了age方法下的 ‘return self.__age’
@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。
import time #引用时间模块
class Date():
def __init__(self,year,month,day): #定义一个时间,调用类或者实例化时可以传参
self.year = year
self.month = month
self.day = day
@classmethod #@classmethod 可以调用类
def now(cls): #用cls把类传递过来
print(cls) #打印cls,验证是哪个类在调用它
t = time.localtime() #获得有格式的时间
obj = cls(t.tm_year,t.tm_mon,t.tm_mday) #将时间的对应参数按装饰后的cls传入类属性,隐藏丑陋的接口
return obj #调用时可以直接self.year 即 cls.year , cls.month如此调用
@classmethod
def Euro(cls): #定义一个欧洲时间,以伦敦为例
t=time.localtime(time.time()-28800) #伦敦时间与北京时间差8个时区,减去计算机识别对应的秒数
return cls(t.tm_year,t.tm_mon,t.tm_mday) #同上
class EuroDate(Date): #可以定义一个子类继承自Date类
def __str__(self): #__str__ 定义在类内部,必须返回一个字符串类型,打印由这个类产生的对象时,会触发执行
return '现在是%s年%s月%s日from %s' % (self.year,self.month,self.day,__class__.__name__) #格式化输出这个str
n = Date(1,1,1) #由于定义类时设置了3个参数,所以这里实例化要传参
n1 = n.now() #经过@classmethod 实例一样可以像类一样调用内部方法。
print(n1.year,n1.month,n1.day)
e1 = EuroDate.Euro() #使用子类调用继承的父类的方法
print(e1)
输出:
<class ‘main.Date’>
2017 4 22
<class ‘main.EuroDate’>
现在是2017年4月21日from EuroDate
@staticmethod
staticmethod #类的工具包 给类用,函数不用传值,不用绑定传self,都可以调用这个函数
作者:李保银
链接:https://www.zhihu.com/question/20021164/answer/18224953
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
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()
23
>>> ik.smethod()
Static: ()
>>> ik.cmethod()
Class: (<class '__main__.Kls'>,)
>>> Kls.printd()
TypeError: unbound method printd() must be called with Kls instance as first argument (got nothing instead)
>>> Kls.smethod()
Static: ()
>>> Kls.cmethod()
Class: (<class '__main__.Kls'>,)
一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法。
而使用@staticmethod或@classmethod,就可以不需要实例化,直接类名.方法名()来调用。
这有利于组织代码,把某些应该属于某个类的函数给放到那个类里去,同时有利于命名空间的整洁。
既然@staticmethod和@classmethod都可以直接类名.方法名()来调用,那他们有什么区别呢
从它们的使用上来看,
@staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。
@classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。
如果在@staticmethod中要调用到这个类的一些属性方法,只能直接类名.属性名或类名.方法名。
而@classmethod因为持有cls参数,可以来调用类的属性,类的方法,实例化对象等,避免硬编码。