组合与封装
第1章 组合与封装
作用:
解决类与类之间代码冗余问题有两种解决方案:1、继承 2、组合
继承:描述的是类与类之间,什么是什么的关系
1.1 组合
组合:描述的是类与类之间的关系,是一种什么有什么关系
一个类产生的对象,该对象拥有一个属性,这个属性的值是来自于另外一个类的对象
组合练习示例:
class Date: def __init__(self,year,mon,day): self.year = year self.mon = mon self.day = day def tell_birth(self): print('出生年月日<%s-%s-%s>' % (self.year, self.mon, self.day)) class OldboyPeople: school = 'oldboy' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex class OldboyTeacher(OldboyPeople): def __init__(self,name,age,sex,level,salary): super().__init__(name,age,sex) self.level=level self.salary=salary def change_score(self): print('teacher %s is changing score' %self.name) class Oldboystudent(OldboyPeople): def __init__(self,name,age,sex,course,): super().__init__(name,age,sex,) self.course=course def choose(self): print('student %s choose course' %self.name) tea1=OldboyTeacher('egon',18,'male',9,3.1) date_obj=Date(2000,1,1) # date_obj.tell_birth() tea1.birth=date_obj # print(tea1.birth) # tea1.birth.tell_birth() # tea1.change_score() stu1=Oldboystudent('张三',16,'male','linux') stu1.birth=Date(2002,3,3) stu1.birth.tell_birth()
1.2 如何封装
1.2.1 什么是封装?
装就是把一堆属性存起来,封的概念就把这些属性给隐藏起来
强调:封装单从字面意思去看等同于隐藏,但其实封装绝对不是单纯意义的隐藏
1.2.2 为什么要用封装?
1、 封装数据属性的目的:把数据属性封装起来,然后需要开辟接口给类外部的使用者使用,好处是我们可以在接口之上添加控制逻辑,从而严格空间访问者对属性的操作
2、 封装函数属性的目的:为了隔离复杂度
3、 封装的终极奥义:明确地区分内外,对外是隐藏的,对内是开放的
1.2.3 如何用封装?
示例:
# class People: # def __init__(self,name,age): # self.__name=name # self.__age=age # # def tell_info(self): # # u=input('user>>: ').strip() # # p=input('pwd>>: ').strip() # # if u == 'egon' and p == '123': # print(self.__name,self.__age) # # def set_info(self,name,age): # if type(name) is not str: # raise TypeError('用户名必须为str类型') # if type(age) is not int: # raise TypeError('年龄必须为int类型') # self.__name=name # self.__age=age # # p=People('egon',18) # # # p.tell_info() # # p.tell_info() # # # p.set_info('EGON',19) # # p.tell_info() # # # p.set_info(353535353535353535,20) # p.set_info('EGON','20')
示例:
class ATM: def __card(self): print('插卡') def __auth(self): print('用户认证') def __input(self): print('输入取款金额') def __print_bill(self): print('打印账单') def __take_money(self): print('取款') def withdraw(self): self.__card() self.__auth() self.__input() self.__print_bill() self.__take_money() obj=ATM() obj.withdraw()
第2章 封装之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 People: def __init__(self,name,weight,height): self.name=name self.weight=weight self.height=height @property def bmi(self): return self.weight / (self.height * self.height) egon=People('egon',75,1.80) # egon.bmi = egon.weight / (egon.height * egon.height) ##加上@property 这条会报错 print(egon.bmi) yl=People('yangli',85,1.74) # yl.bmi=yl.weight / (yl.height * yl.height) ##加上@property 这条会报错 print(yl.bmi)
2.1 讲解
首先需要明确。bmi是算出来的,不是一个固定死的值,也就说我们必须编写一个功能,每次调用该功能都会立即计算一个值.
egon=People('egon',75,1.80) yl=People('yangli',85,1.74)
但很明显人的bmi值听起来更像一个名词而非动词
print(egon.bmi()) print(yl.bmi())
于是我们需要为bmi这个函数添加装饰器,将其伪装成一个数据属性
egon.weight=70 print(egon.bmi) #21.604938271604937,调用egon.bmi本质就是触发函数bmi的执行,从而拿到其返回值 print(yl.bmi)
2.2 了解
# egon.bmi=123 # egon.bmi背后对应的是一个函数,所以不能赋值
class People: def __init__(self,name): self.__name=name @property def name(self): #obj.name print('您现在访问的是用户名。。。') return self.__name @name.setter #obj.name='EGON' def name(self,x): # print('=================',x) if type(x) is not str: raise TypeError('名字必须是str类型,傻叉') self.__name=x @name.deleter def name(self): # print('就不让你删') del self.__name obj=People('egon') # print(obj.name) # print(obj.name()) # print(obj.name) # obj.name='EGON' # print(obj.name) # obj.name=123 del obj.nam