在编程里经常用的是实例方法,直接用实例去调用, 只要 方法里有self 就可以断定是实例方法,
如 def method_name(self,*argc). 先看下边代码如下:
class Date:
def __init__(self,year,month,day):
self.year=year
self.month=month
self.day=day
def __str__(self):
return ("{year}-{month}-{day}").format(year=self.year,month=self.month,day=self.day)
def yesterday(self):
self.day-=1
date=Date(2018,10,20)
print(date)
date.yesterday()
print(date)
#打印结果
2018-10-20
2018-10-19
先说下 date.yesterday() ,实例直接调用方法名 ,会转化为 yesterday(date), 改变了实例的属性 day ,这也只是改变了实例的属性,并不会改变类的变量(这个在前面已经讲过了)。如果我就想在方法里改变类的变量怎么做呢?看下边的代码。
class Date:
day=10 #添加 类属性 day
def __init__(self,year,month,day):
self.year=year
self.month=month
self.day=day
def __str__(self):
return ("{year}-{month}-{day}").format(year=self.year,month=self.month,day=self.day)
def yesterday(Date):
Date.day-=1 #对类进行修改, 记住用的是Date.day ,如果是实例方法必须是 self.
date=Date(2018,10,20)
print(date)
#打印结果 实例传入 day =20, 就用实例的20,不会找 类的a=10
2018-10-20
Date.yesterday(Date)
print(date)
#打印结果 如下, 这个全部用的是类,跟self 没有关系,所以还是打印结果不变。
2018-10-20
print(Date.day)
#打印结果 调用修改类属性方法 生效。 如果self 没有day 这个属性,他一定去找类的变量 day, 这个可以自己尝试下。
9
上边的有点扯远了, 也算复习下 类变量和实例变量的关系。
下边正式介绍 静态方法,我们之前想创造一个实例都是用 Date(2018,10,20),现在升级了, 假如我们想传递直接字符串的形式怎么办呢? 例如 “2018-01-01” or “2018/01/01" 如果直接传递百分之百错误。如果不用静态方法,我们首先用到的是,先把 这个字符串转化为 2018,01,01 这种形式再传递, 先看下边的代码就是这样形式。
year,month,day=tuple("2018-10-10".split("-"))
print(year,month,day)
#打印结果 转化成功, 再拿转化后的进行传值,
#2018 10 10
缺点是每次实例化都要调用这段代码,代码量自己想想, 有没有好的方法呢, 就用 静态方法可以解决这个问题,小白该说了,我直接定义个实例化方法不行了吗? 懂行的人会笑坏大牙,这里不做解释了,自己想想吧。
下边就开始用静态方法了 ,代码如下:
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def __str__(self):
return ("{year}-{month}-{day}").format(year=self.year, month=self.month, day=self.day)
def yesterday(Date):
Date.day -= 1
@staticmethod # 用这个装饰器表明是静态方法,这个要注意。
def static(date_str):
year, month, day = tuple(date_str.split("-"))
return Date(int(year), int(month), int(day))
new_day=Date.static("2018-10-10") #由于静态方法不属于实例 所以调用的时候, 用类名.静态方法,这个要注意
print(new_day)
#打印结果 正好是咱们的预期结果。
2018-10-10
以上用静态方法初始化数据,代码变短简洁 ,易读性提高。 假如我们要修改类名Date变成New_date,这个时候我们要同时修改所有调用的类名。比如上边的 return Date (int(year), int(month), int(day)),这个就是硬编码的形式。有没有办法不用修改,哈哈 当然有了。就是类方法能解决。
静态方法用 @staticmethod 标识, 类方法同样也有装饰器用 @classmethod ,实例方法传递的是self,类同样也是对象直接传递cls就行。
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def __str__(self):
return ("{year}-{month}-{day}").format(year=self.year, month=self.month, day=self.day)
def yesterday(Date):
Date.day -= 1
# @staticmethod
#def static(date_str):
# year, month, day = tuple(date_str.split("-"))
# return Date(int(year), int(month), int(day))
@classmethod #类方法的标识
def class_method(cls,date_str): # 这个cls只是表明类对象,是可以修改的,同样你改为self也是一样,叫cls为了提高可读性。
year, month, day = tuple(date_str.split("-"))
return cls(int(year), int(month), int(day)) #这个cls 和上边是一样的意思,这个就比静态方法好处就是会随便类名变化而变化。
new_day=Date.class_method("2018-10-10")
print(new_day)
#打印结果
2018-10-10
我这样一比较,小伙伴该认为以后就没有用静态方法,反正类方法可以替代并且优越于他,存在就有合理的地方,下边我介绍静态方法的适合他的应用场景之一是校验传入值。请看下边的代码,是类方法和静态方法的结合。
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def __str__(self):
return ("{year}-{month}-{day}").format(year=self.year, month=self.month, day=self.day)
def yesterday(Date):
Date.day -= 1
@staticmethod #校验输入值类型和大小是否符合咱们的类型。
def var_str(date_str):
year, month, day = tuple(date_str.split("-"))
if 0 < int(year) and 0 < int(month) <= 12 and 0 < int(day) < 32:
return True
else:
return False
@classmethod
def class_method(cls, date_str):
if cls.var_str(date_str): #这里是调用静态方法,注意要用cls.静态方法,原理和实例方法中的self一样,自己可以试试,否则是不能读取的。
year, month, day = tuple(date_str.split("-"))
return cls(int(year), int(month), int(day))
new_day = Date.class_method("2018-10-10")
print(new_day)
# 打印结果
2018 - 10 - 10
总结下 为什么这样结合呢, 校验方法和初始化数据方法分开,代码的逻辑清晰, 就像前端和后端要分离一样的道理。 用的最多的是实例方法。
实例方法 用self标识,一般用实例调用, 静态方法标识是 @staticmethod用类名去调用,类方法优于静态方法解决了静态方法的类名的硬编码, 在不同的场景搭配不同方法为了达到代码的可读性简洁。