python基础——特性(property)
1 什么是特性property
property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值
import math class Circle: #定义一个圆的类 def __init__(self,radius): #圆的半径radiu self.radius=radius @property # are=property(area) def area(self): #计算面积 return math.pi*self.radius**2 @property # def perimeger(self): #计算周长 return math.pi*self.radius c=Circle(7) print(c.radius) #半径 c.radius=10 # print(c.area()) #面积 # print(c.perimeger()) #周长 print(c.area) #可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值 print(c.perimeger)
输出结果为:
7 314.1592653589793 31.41592653589793
2 为什么要用property
将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则
被property装饰的属性会优先于对象的属性被使用
而被property装饰的属性,如sex,分成三种
1.Property
2.sex.setter 赋值修改
3.sex.deleter 删除
class People: def __init__(self,name,SEX): self.name=name self.sex=SEX #p1.sex='male' 这个调用的是 setter里面的sex @property def sex(self): # print('------>') return self.__ABCDEF @sex.setter def sex(self,value): print("=====>") # self.__sex=value # if not isinstance(value,str): # raise TypeError('性别必须是字符串类型') #自己定义报异常 self.__ABCDEF=value #p1.ABCDEF= 'male' @sex.deleter def sex(self): raise Exception('不让删除') p1=People('alex','male') p1.sex #查看的是 property 里面的sex 真实的sex被隐藏在ABCEF里面 print(p1.sex) # p1.sex #sex的位置 先去property里面查找 如果有就直接打印 # p1.sex='male' # del p1.sex #删除sex 就去找deleter下删除 #删除想要的都是自己控制的 可以报异常不让操作
3 封装与扩展性
封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。
class People: def __init__(self,name,age,height,weight): self.name=name self.age=age self.height=height self.weight=weight @property def bodyindex(self): return self.weight/(self.height**2) p1=People("allen",21,1.73,55) print(p1.bodyindex)
4 静态方法和类方法
通常情况下,在类中定义的所有函数(注意了,这里说的就是所有,跟self啥的没关系,self也只是一个再普通不过的参数而已)都是对象的绑定方法,对象在调用绑定方法时会自动将自己作为参数传递给方法的第一个参数。除此之外还有两种常见的方法:静态方法和类方法,二者是为类量身定制的,但是实例非要使用,也不会报错
4.1 静态方法(@staticmethod)
是一种普通函数,位于类定义的命名空间中,不会对任何实例类型进行操作,python为我们内置了函数staticmethod来把类中的函数定义成静态方法
1 没有加装饰器的效果
class Foo: def spam(x,y,z): print(x,y,z) Foo.spam(1,2,3)
class Foo: def spam(self): print("---->") # Foo.spam(1) 对于类调用需要传参数 f1=Foo() #实例化对象 f1相当于self f1.spam() #对象再去调用
2 加上装饰器的效果 @staticmethod
class Foo: @staticmethod def spam(x,y,z): Foo.spam(1,2,3) #不是一个绑定方法 相当于一个函数 有几个值需要传几个值
应用场景:编写类时需要采用很多不同的方式来创建实例,而我们只有一个__init__函数,此时静态方法就派上用场了
class Date: def __init__(self,year,month,day): self.year=year self.month=month self.day=day @staticmethod def now(): #用Date.now()的形式去产生实例,该实例用的是当前时间 t=time.localtime() #获取结构化的时间格式 return Date(t.tm_year,t.tm_mon,t.tm_mday) #新建实例并且返回 @staticmethod def tomorrow():#用Date.tomorrow()的形式去产生实例,该实例用的是明天的时间 t=time.localtime(time.time()+86400) return Date(t.tm_year,t.tm_mon,t.tm_mday) a=Date('1987',11,27) #自己定义时间 b=Date.now() #采用当前时间 c=Date.tomorrow() #采用明天的时间 print(a.year,a.month,a.day) print(b.year,b.month,b.day) print(c.year,c.month,c.day)
4.2 类方法 (@classmethod)
类方法是给类用的,类在使用时会将类本身当做参数传给类方法的第一个参数,python为我们内置了函数classmethod来把类中的函数定义成类方法
classmethod:把一个方法绑定给类:类.绑定到类的方法(),会把类本身当做第一个参数自动给绑定到类的方法
class Foo: def bar(self): pass @classmethod #把一个方法绑定给类:类.绑定到类的方法(), #会把类本身当做第一个参数自动给绑定到类的方法 def test(cls,x): print(cls,x) #拿到一个类的内存地址后,就可以实例化或者引用类的属性了 # print(Foo.bar) print(Foo.test)
# Foo.test(123)#绑定到类的方法 第一个参数是把类给传进去。
应用场景:
class Date: def __init__(self,year,month,day): self.year=year self.month=month self.day=day @classmethod def tomorrow(cls): t=time.localtime(time.time()+86400) return cls(t.tm_year,t.tm_mon,t.tm_mday) class Beijing(Date): def __str__(self): return "年:%s,月:%s,日:%s"%(self.year,self.month,self.day) b=Beijing.tomorrow() print(b)
强调,注意注意注意:静态方法和类方法虽然是给类准备的,但是如果实例去用,也是可以用的,只不过实例去调用的时候容易让人混淆,不知道你要干啥
小结:
1.绑定到对象的方法
只要是在类内部定义的,并且没有被任何装饰器修饰过的方法,都是绑定到对象的
绑定到对象,指的是:就给对象去用,
使用方式:对象.对象的绑定方法(),不用为self传值
特性:调用时会把对象本身当做第一个参数传给对象的绑定方法
2.绑定到类的方法:classmethod
在类内部定义的,并且被装饰器@classmethod修饰过的方法,都是绑定到类的
绑定到对象,指的是:就给对象去用
使用方式:对象.对象的绑定方法()
特性:调用时会把对象本身当做第一个参数传给对象的绑定方法
3.什么是解除绑定的函数
解除绑定的方法:staticmetho
既不与类绑定,也不与对象绑定,不与任何事物绑定
绑定的特性:自动传值(绑定到类的就是自动传类,绑定到对象的就自动传对象)
解除绑定的特性:不管是类还是对象来调用,都没有自动传值这么一说了
4.什么是property,如何定义,如何使用,给谁用,什么情况下应该将一个属性定义成property,有什么好处?
property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值
以property作为装饰器装饰函数
需要将一个函数封装成一个私有的时候
将函数设置为私有的,遵循同一访问,让对象以为访问的是一类(其实是一个函数)