一.特性(property,setter,deleter)
1.属性:将一个方法伪装成一个属性,在代码级别上没有本质的提升,但是看起来更合理;
class Person: def __init__(self, height, weight): self.height = height self.weight = weight def bmi(self): return format(self.weight / (self.height ** 2), '.2f' p = Person(1.72, 67) print(p.bmi()) #这里bmi是计算出来的,所以更像是名词,不应该作为方法调用;
所以我们要修改一下,将方法bmi封装成一个属性;
class Person: def __init__(self, height, weight): self.height = height self.weight = weight @property def bmi(self): return format(self.weight / (self.height ** 2), '.2f') p = Person(1.72, 67) print(p.bmi)
#property是一种特殊的属性,访问它时会执行一段功能然后返回,试用于能够直接返回值的,通过自己本身计算的,就要把它变成属性方法更合理;
类似的还有求圆的面积和周长;
2.setter可以对属性值进行修改,但是只能传入一个值,deleter可以删除属性的值;
class Person: def __init__(self,name,age): self.name = name self.__age = age if type(age) is int else '你输入有误' @property def age(self): return self.__age @age.setter def age(self,r): self.__age = r if type(r) is int else '你输入有误' @age.deleter def age(self): del self.__age p = Person('刘博文', 5) print(p.age) p.age = 6 #执行setter语句,修改了方法的属性值,只能传入一个参数 print(p.age) del p.age #执行deleter语句,删除方法里的值
二.类方法
1.两个前面内容:a:不要用类名直接调用方法;因为里面必须得传值给self,
# 类方法 class A: def func(self): # 普通方法 print(self) @classmethod # 类方法 def func1(cls): print(cls) a1 = A() #可以通过实例化一个对象, a1.func() #这里不用传值,默认会传入对象本身; A.func(11) #用类调用方法,要传入一个值给self;
这里的类方法,通过类名调用的方法,上面加一个装饰器@classmethod下面的方法就是类方法;
# a1 = A() # a1.func1() # 对象调用类方法,cls 得到的是类本身.
类方法中的第一个参数约定俗成cls,Python中自动将类名(类空间)传给cls,不管是谁调用类方法,cls指的都是类本身;
a:类方法的应用场景:
1).类中有些方法是不需要对象参与的
class A: name = 'alex' count = 1 @classmethod def func1(cls): # 此方法无需对象参与 return cls.name + str(cls.count + 1) print(A.func1())
2)这里如果用return A.name + str(A.count + 1)不用cls的话,要是改变一下类名,那底下也得改变;
所以对类中的静态变量进行改变,要用类方法;
class People: NAME = 'ALEX' COUNT = 0 @classmethod def create_name(cls): cls.COUNT += 1 print(cls) print(cls.new(cls)) #2.执行.new函数的时候执行了将cls这个类传给了self return cls.NAME + str(cls.COUNT) def new(self): self.age = 10 #3.执行.new方法的时候相当于执行了类.age = 10 return self.age p = People() print(p.create_name()) #1.对象调用类方法,cls就是接收的是对象所在的类 print(p.__dict__) #4.所以这里面为空字典{} print(People.__dict__) #5.这里面还有age
3)继承中,父类得到子类的类空间;
#前面说我们父类调用和查找不到子类的空间,但是通过类方法,父类也可以得到子类空间,为所欲为;
class A: age = 12 @classmethod def func1(cls): # 这里cls传入的是调用者B,父类得到了子类的空间; print(cls) # 对B类的所有的内容可以进行修改. print(cls.age) # return cls.name + str(cls.count + 1) class B(A): age = 22 B.func1()
#如果没有类方法,你也可以得到子类的所有东西
class A: age = 12 def func2(self): print(self) # self 子类的对象,能得到子类 空间的任意值 class B(A): age = 22 b1 = B() b1.func2()
这里用self也可以得到子类的东西;但是只能查,不能改;
4)静态方法:
class A: @staticmethod def login(username, password): if username == 'alex' and password == 123: print('登录成功') else: print('登录失败...') A.login('alex',1234)
def login(username,password): if username == 'alex' and password == 123: print('登录成功') else: print('登录失败...') login('alex',1234)
这两段代码执行效果一样,虽然你用函数也可以实现,但是这样不合适;
所以类方法的好处就是 1.代码块,清晰 2.提高代码的复用性;