property
首先我们来看一个例子:
''' BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解) 成人的BMI数值: 过轻:低于18.5 正常:18.5-23.9 过重:24-27 肥胖:28-32 非常肥胖, 高于32 体质指数(BMI)=体重(kg)÷身高^2(m) EX:70kg÷(1.75×1.75)=22.86 ''' class Peopele: def __init__(self,name,weight,higiht): self.name=name self.weight=weight self.higiht=higiht def bmi(self): return self.weight/(self.higiht*self.higiht) obj=Peopele('egon',75,1.75) print(obj.bmi())
从列子当中 我们可以的看出 bmi是一个跟体重,身高一样的名词,我们却用调用动词的方式加括号去调用它,这样就会导致 不知情的人去调用bmi这个名词 却要先找到它所对应的函数 然后再用调用 函数的方式 去调用它,怎么样能像调用身高,体重那样去调用bmi那 我们就需要用到property,请看下面:
#使用property(装饰器,将其伪装成一个数据属性) class Peopele: def __init__(self,name,weight,higiht): self.name=name self.weight=weight self.higiht=higiht @property def bmi(self): return self.weight/(self.higiht*self.higiht) obj=Peopele('egon',75,1.75) print(obj.bmi)
有一点需要注意 因为bmi的本质是个函数,它只是被property伪装成一个数据属性 所以我们无法去赋值
我们举个实际例子 来说明property的牛逼之处
#使用property的实际例子对比 # 没有使用 class School: def __init__(self,name): self.__name=name def get_name(self): return self.__name def setter_name(self,x): if type(x) is not str: raise TypeError('名字必须是str类型,傻叉') self.__name=x def del_name(self): print('就不让你删') del self.__name res=School('egon') res.setter_name('EGON') print(res.get_name()) del res.del_name # print(res.get_name) #报错 EGON Traceback (most recent call last): File "C:/Users/64802/PycharmProjects/kaoshi/学习/学习/day22/property.py", line 52, in <module> del res.del_name AttributeError: del_name #不是报找不到slef.name这个值的错误 就说明 我们没有成功删掉 class School: def __init__(self,name): self.__name=name @property def get_name(self): return self.__name @get_name.setter def setter_name(self,x): if type(x) is not str: raise TypeError('名字必须是str类型,傻叉') self.__name=x @get_name.deleter def del_name(self): print('就不让你删') del self.__name res=School('egon') res.setter_name='EGON' print(res.get_name) del res.del_name print(res.get_name) #报错说 我找不到学校名字这个值 说明删除成功 AttributeError: 'School' object has no attribute '_School__name'
上述例子中@都是一些固定的用法记住既可以,我们的调用完全符合了我们所需要的
多态
1 什么是多态
多态指的是同一种事物多种形态
2、为什要用多态
用基类创建一套统一的规则,强制子类去遵循(使用抽象类实现),这样便可以
在不用考虑对象具体类型的前提下而直接使用对象下的方法
#都是一些固定用法 记住即可 意思就是强制你父类有什么 是什么样的函数你必须一样 不然就会在调用阶段报错,我们也知道在定义阶段 #只会执行类体内代码,把产生的名字放进存在类的名称空间,函数的话只会检测函数体内语法 import abc class 动物(metaclass=abc.ABCMeta): @abc.abstractclassmethod def eat(self): print('eat') @abc.abstractclassmethod def run(self): print('run') class Cat(动物): def eat(self): print('cat eat') def run(self): print('cat run') class Dog(动物): def eat(self): print('dog eat') def run(self): print('dog run') res=Cat() res.eat()
鸭子类型
#鸭子类型(走路像鸭子,看起来像鸭子,你就是鸭子) class Disk: def read(self): print('disk read') def write(self): print('disk write') class Txt: def read(self): print('txt read') def write(self): print('txt write') class Process: def read(self): print('process read') def write(self): print('process write') obj1=Disk() obj2=Txt() obj3=Process() obj1.read() obj2.read() obj3.read() #我们俗成规定并没有什么强制性,符合python的风格,它的意思是和多态一样的 但是没有父类子类一说
classmethod
绑定方法:
在类内部定义的函数,默认就是给对象来用,而且是绑定给对象用的,称为对象的绑定方法
绑定对象的方法特殊之处:
应该由对象来调用,对象来调用,会自动将对象当作第一个参数传入
绑定到类的方法特殊之处:
应该由类来调用,类来调用,会自动将类当作第一个参数传入
import settings class People: def __init__(self,name,age): self.__name=name self.__age=age def info(self): print(''' 姓名:%s 年龄:%s '''%(self.__name,self.__age)) @classmethod def get_info(cls): return cls(settings.name,settings.age) obj=People.get_info() obj.info()
staticmethod:非绑定方法,就是一个普通函数
import setttings import hashlib import time class People: def __init__(self,name,age): self.uid=self.create_id() self.name=name self.age=age def tell(self): print('%s: %s:%s' %(self.uid,self.name,self.age)) @classmethod def from_conf(cls): return cls(settings.NAME,settings.AGE) @staticmethod def create_id(): m=hashlib.md5() m.update(str(time.clock()).encode('utf-8')) return m.hexdigest() obj=People('egon',18) # print(obj.uid,obj.name,obj.age) # obj.tell() # print(obj.create_id) # print(People.create_id) print(obj.create_id()) print(People.create_id())
特性:既不跟类绑定,也不跟对象绑定,这意味着谁都能用
谁来用都是一个普通函数,也就是说没有自动传值的特性了