1.属性
引:计算一个人的MBI值
class People: def __init__(self,name,weight,hight): self.name = name self.__weight = weight self.__hight = hight def EX(self): result = self.__weight/(self.__hight**2) print("%s的BMI值为%s"% (self.name,result)) p1 = People("Tom",60,1.75) p1.EX() 输出: Tom的BMI值为19.591836734693878
问题:对于如上程序虽然实现了功能,但是BMI值是一个名词(就应该封装到属性中),但是上述程序是通过一个方法计算出来的,相当于一个动词
1)属性:将一个方法伪装成一个属性,在代码的级别上没有本质的提升,但是让其看起来更加合理了
2)使用:在方法前加上@property这个装饰器,修饰方法,那么这个方法在调用时就不需要加括号了
class People: def __init__(self,name,weight,hight): self.name = name self.__weight = weight self.__hight = hight @property def EX(self): #伪装成属性 result = self.__weight/(self.__hight**2) print("%s的BMI值为%s"% (self.name,result)) p1 = People("Tom",60,1.75) p1.EX 输出: Tom的BMI值为19.591836734693878
3)将一个方法伪装后的属性改值
#如果在类中被@property和 @方法名.setter装饰器修饰的方法都存在,然后对被伪装的属性改值,那么就会自动执行被@方法名.setter修饰的方法,并且将要改的值传给被@方法名.setter装饰器修饰的方法的self参数后的参数
class People: def __init__(self,name,weight,hight): self.name = name self.__weight = weight self.__hight = hight @property def EX(self): #伪装成属性 result = self.__weight/(self.__hight**2) print("%s的BMI值为%s"% (self.name,result)) @EX.setter def EX(self,a1): print(a1) print("自动被执行。。。") p1 = People("Tom",60,1.75) p1.EX = 18 #不需要括号,直接调用 输出: 18 666
注:若要改属性的值,两个装饰器缺一不可
#例:修改被伪装的属性的值
class Person: def __init__(self,name,age): self.name = name self.__age = age @property def age(self): return self.__age @age.setter def age(self,a1): if type(a1) is int: self.__age = a1 else: print("你输入的值有误") p1 = Person("阿狸",18) print(p1.age ) p1.age = 20 print(p1.age) 输出: 18 20 说明:首先实例化一个对象,传进去阿狸和18,实例化时自动执行__init__方法,执行时封装了一个名字name;p1.age让别然看来调用的就是p1对象的属性,@procerty就是将age方法伪装成一个属性,然后通过p1.age相当于执行age方法,返回__age私有变量值;p1.age = 20是对属性进行改变,只要值一改变就会自动的执行被@age.setter修饰的方法,并且将要改变的值传给方法的第二个参数
4)删除被伪装的属性【方法名.delerter】
class Person: def __init__(self,name,age): self.name = name self.__age = age @property def age(self): return self.__age @age.setter def age(self,a1): if type(a1) is int: self.__age = a1 else: print("你输入的值有误") @age.deleter def age(self): print("使用del,自动被执行..") del self.__age #删除私有变量 p1 = Person("阿狸",18) print(p1.age ) del p1.age 输出: 18 使用del,自动被执行..
总结:可理解为一个执行触发一个方法5)使用场景:property用于类似于求BMI这种,看似是一个名词,但是实际需要计算的,都用property装饰
2.类方法
#通过对象调用类的普通方法,会将对象地址传给普通方法的参数self
class A: def func(self): #普通方法 print(self) a1 = A() a1.func() #通过对象调用普通方法 A.func(a1) #通过类名调用普通方法 输出: <__main__.A object at 0x0000025F5AB75EB8> <__main__.A object at 0x0000025F5AB75EB8>
1)类方法:就是在普通方法前,通过装饰器@classmethod修饰,再通过类名调用的方法,类方法种第一个参数约定俗成为cls,python自动将类名(类空间)传给cls
class A: @classmethod def func(cls): #类方法 print(cls) A.func() 输出: <class '__main__.A'>
#如果是对象调用类方法,cls得到的是类本身
class A: @classmethod def func(cls): #类方法 print(cls) a = A() a.func() 输出: <class '__main__.A'>
2)类方法应用场景
①类中有些方法是不需要传入对象的,即不要对象的一起东西
#对于如下程序,完全不需要实例化对象,但是直接用类名调用函数会出错,需要再类名调用函数时传参
class Person: name = "阿狸" age = 18 def func(self): return Person.name+str(Person.age) print(Person.func(1)) p = Person() print(p.func()) 输出: 阿狸18 阿狸18
#通过类方法时,不再需要创建对象
class Person: name = "阿狸" age = 18 @classmethod def func(cls): return cls.name+str(cls.age) print(Person.func()) 输出: 阿狸18
②对类中的静态变量进行改变时,要用到类方法
class Person: name = "阿狸" age = 18 @classmethod def func(cls): return cls.name+str(cls.age) #就不再通过【类名.变量】的方式去改变静态变量 print(Person.func()) 输出: 阿狸18
③继承中,父类得到子类的类空间(父类可对子类的所以内容进行修改)
class A: @classmethod def func(cls): #类方法 print(cls) #父类中得到了子类的类空间 print(cls.age) class B(A): age = 22 def func_b(self): pass B.func() #子类调用方法,先在子类找,子类找不到,去父类找,父类就得到了子类的类空间 输出: <class '__main__.B'> 22
3.静态方法
1)通过装饰器@staticmethod修饰的方法,不需要给方法传递任何的参数,即相当于在类中定义了一个普通函数,不需要传递对象、类等参数
class A: @staticmethod def func(): #静态方法 print(666) A.func() 输出: 666
2)静态方法优点
①在整体代码解构来说,使用静态方法(将方法写到类中)比较清晰,是一个代码块
②静态方法可提高代码的复用性
4.python2.x和python3.x的区别
1)python2.x:各种大牛按照自己代码的习惯给python贡献源码(java的源码习惯,C#源码的小习惯),导致源码混乱,重复
①python2.x中的输出是print() print
②python2.x中的range就是一个列表[1,2,3]
③python2.x中的输入时raw_input(); input()只允许输入数字
模块、项目等等区别
2)python3.x:龟叔重写,源码优美、清晰、简单,2020年python2.x不再更新
①python3.x中的输出是print()
②Python3.x中,range是一个可迭代对象
③python中的输入是input()
模块、项目等等区别
3)将一个方法伪装后的属性改值
如果在类中被@property和 @方法名.setter装饰器修饰的方法都存在,然后对被伪装的属性改值,那么就会自动执行被@方法名.setter修饰的方法,并且将要改的值传给被@方法名.setter装饰器修饰的方法的self参数后的参数