注意:光理论是不够的,在此送大家一套2020最新Python全栈实战视频教程,点击此处 进来获取 跟着练习下,希望大家一起进步哦! 面向对象编程有三大特性:封装、继承、多态,其中最重要的一个特性就是封装。 Python的Class机制 定义属性就是为了使用,所以隐藏并不是目的 将数据隐藏起来就 总结隐藏属性与开放修改、访问数据属性的接口, 身高或体重是不断变化的,因而每次想查看BMI值都需要通过计算才能得到,但很明显BMI听起来更像是一个特征而非功能,为此Python专门 使用property有效地保证了属性访问的一致性。另外property还提供设置和删除属性的功能,如下 注意:我们都知道隐藏数据属性,是为了提供接口,更规范的访问,文章目录
一、面向对象编程实战演练
1、学校类(关联班级)
# 一、学校---# 校区创建完毕后,可以为每个校区创建班级 # 定义学校类 class School: school_name = 'OLDBOY' def __init__(self, nickname, addr): self.nickname = nickname self.addr = addr self.classes = [] # 为【学校】关联【班级】 def related_class(self, class_obj): # self.classes.append(班级名字) # self.classes.append(class_name) self.classes.append(class_obj) # 函数功能:打印每个校区的每个班级的课程信息 def tell_class(self): # 改 # 打印的校区的名字 print(self.nickname.center(60,'=')) # 格式化打印效果:==========================校区名称=========================== # 打印班级开设的课程信息 for class_obj in self.classes: class_obj.tell_course() # 实例化学校类 school_obj1=School('老男孩魔都校区','上海') school_obj2=School('老男孩帝都校区','北京')
2、班级类(关联课程)
# 二、班级---# 班级创建完毕后,可以为每个班级创建课程 # 定义班级类 class Class: def __init__(self, name): self.name = name self.course = None # 为【班级】关联【课程】 def related_course(self, course_obj): # self.course = course_name self.course = course_obj def tell_course(self): print('%s' % self.name,end=" ") # 打印班级信息 self.course.tell_info() # 打印课程的详细信息 # def related_student(self,student_obj): # self.student = student_obj def tell_class(self): print('%s'%self.name) self.tell_course() # 实例化班级 # 1、创建班级 class_obj1 = Class('脱产14期') class_obj2 = Class('脱产15期') class_obj3 = Class('脱产29期') # 4、为学校开设班级(为【学校】关联【班级】) # 上海校区开了:脱产14期,上海校区开了脱产15期 school_obj1.related_class(class_obj1) school_obj1.related_class(class_obj2) # 北京校区开了:脱产29期 school_obj2.related_class(class_obj3)
3、课程类
# 三、课程类 # 定义课程类 class Course: def __init__(self,name,period,price): self.name=name self.period=period self.price=price def tell_info(self): print('<课程名:%s 周期:%s 价钱:%s>' %(self.name,self.period,self.price)) # 实例化课程类 # 1、创建课程 course_obj1=Course('python全栈开发','6mons',20000) course_obj2=Course('linux运维','5mons',18000) # 3、为【班级】关联【课程对象】 class_obj1.related_course(course_obj1) class_obj2.related_course(course_obj2) class_obj3.related_course(course_obj1) # 【查询一】 # 查看每个校区的每个班级的课程信息(先是为【学校】关联【班级】,再为【班级】关联【课程】) # tell_class(tell_course())--- tell_course(tell_info())---tell_info(课程信息) # school_obj1.tell_class() # school_obj2.tell_class() # 输出结果: # ==========================老男孩魔都校区=========================== # 脱产14期 <课程名:python全栈开发 周期:6mons 价钱:20000> # 脱产15期 <课程名:linux运维 周期:5mons 价钱:18000> # ==========================老男孩帝都校区=========================== # 脱产29期 <课程名:python全栈开发 周期:6mons 价钱:20000>
4、学生类(关联学校、班级)
# 四、学生类--# 学生创建完毕后,学生可以选择班级 # 定义学生类 class Student: def __init__(self,s_school,s_name,s_age,s_number,s_gender): self.stu_school = s_school self.stu_name = s_name self.stu_age = s_age self.stu_number = s_number self.stu_gender = s_gender # def choose_class(self,class_obj): # 学生创建完毕后,学生可以选择班级 # self.classes= class_obj # 为【学生】关联【学校】 def related_school(self,school_obj): self.stu_school= school_obj # 为【学生】关联【班级】 def related_class(self,class_obj): self.stu_class= class_obj def tell_stu_message(self): print(('学生 %s 2020年档案表' %(self.stu_name)).center(60, '=')) print('<学校:%s 姓名:%s 年龄:%s 学号:%s 性别:%s>' %(self.stu_school,self.stu_name,self.stu_age,self.stu_number,self.stu_gender)) # self.stu_class.tell_class() self.stu_class.tell_course() # 实例化学生类 # 1、创建学生 stu_obj1 = Student('老男孩魔都校区','CC',18,2020001,'female') stu_obj2 = Student('老男孩帝都校区','MILI',19,2020007,'male') stu_obj3 = Student('老男孩魔都校区','MELA',20,2020009,'male') # 2、为【学生】关联【班级】 stu_obj1.related_class(class_obj1) stu_obj2.related_class(class_obj2) stu_obj3.related_class(class_obj3) # 【查询二】查询每个学生的学校,班级,课程信息 stu_obj1.tell_stu_message() stu_obj2.tell_stu_message() stu_obj3.tell_stu_message() # 输出结果: # =======================学生 CC 2020年档案表======================= # <学校:老男孩魔都校区 姓名:CC 年龄:18 学号:2020001 性别:female> # 脱产14期 <课程名:python全栈开发 周期:6mons 价钱:20000> # ======================学生 MILI 2020年档案表====================== # <学校:老男孩帝都校区 姓名:MILI 年龄:19 学号:2020007 性别:male> # 脱产15期 <课程名:linux运维 周期:5mons 价钱:18000> # ======================学生 MELA 2020年档案表====================== # <学校:老男孩魔都校区 姓名:MELA 年龄:20 学号:2020009 性别:male> # 脱产29期 <课程名:python全栈开发 周期:6mons 价钱:20000>
二、封装
1、引入
封装指的就是把数据与功能都整合到一起
,听起来是不是很熟悉,没错,我们之前所说的”整合“二字其实就是封装的通俗说法。除此之外,针对封装到对象或者类中的属性,我们还可以严格控制对它们的访问,分两步实现:隐藏与开放接口
2、隐藏属性
采用双下划线开头的方式将属性隐藏起来(设置成私有的)
,但其实这仅仅只是一种变形操作,类中所有双下滑线开头的属性都会在类定义阶段、检测语法时自动变成“_类名__属性名”的形式:
class Foo: __N=0 # 变形为_Foo__N def __init__(self): # 定义函数时,会检测函数语法,所以__开头的属性也会变形 self.__x=10 # 变形为self._Foo__x def __f1(self): # 变形为_Foo__f1 print('__f1 run') def f2(self): # 定义函数时,会检测函数语法,所以__开头的属性也会变形 self.__f1() #变形为self._Foo__f1() # -----------此线以上都是Foo类的定义__开头都会变成_类名__属性名---------------- print(Foo.__N) # 报错AttributeError:类Foo没有属性__N print(Foo._Foo__N) # 正确 obj = Foo() obj.__x = 2 print(obj._Foo__x) # 对象obj没有属性_Foo__x,注意只在类定义阶段才变形成_Foo__x,上面obj.__x = 2,这已经是执行阶段了,因此不会变形,你只是新增了一个__x数据属性而已 print(obj.__x) # 正确,返回结果:2 # 注意: 1. 函数属性和数据属性的隐藏方法一样,隐藏后的外部调用方法也一样 2. 隐藏对外不对内,对外部需要'_类名__属性名'这样访问,内部'__属性名'这样即可 3. 第2点这是为什么呢?,因为对内的都是在类定义阶段,里面的'__属性名'都会转变成'_类名__属性名',因此访问无碍,外面都是执行阶段,不会变形因此无法访问到。
3、为什么要隐藏属性呢?
(1)为什么隐藏数据属性?
限制了类外部对数据的直接操作
,然后类内应该提供相应的接口来允许类外部间接地操作数据
,接口之上可以附加额外的逻辑来对数据的操作进行严格地控制
>>> class Teacher: ... def __init__(self,name,age): #将名字和年纪都隐藏起来 ... self.__name=name ... self.__age=age ... def tell_info(self): #对外提供访问老师信息的接口 ... print('姓名:%s,年龄:%s' %(self.__name,self.__age)) ... def set_info(self,name,age): #对外提供设置老师信息的接口,并附加类型检查的逻辑 ... if not isinstance(name,str): ... raise TypeError('姓名必须是字符串类型') ... if not isinstance(age,int): ... raise TypeError('年龄必须是整型') ... self.__name=name ... self.__age=age ... >>> >>> t=Teacher('lili',18) >>> t.set_info(‘LiLi','19') # 年龄不为整型,抛出异常 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 11, in set_info TypeError: 年龄必须是整型 >>> t.set_info('LiLi',19) # 名字为字符串类型,年龄为整形,可以正常设置 >>> t.tell_info() # 查看老师的信息 姓名:LiLi,年龄:19
(2)为什么隐藏函数属性?
目的的是为了隔离复杂度
,例如ATM程序的取款功能,该功能有很多其他功能组成,比如插卡、身份认证、输入金额、打印小票、取钱等,而对使用者来说,只需要开发取款这个功能接口即可,其余功能我们都可以隐藏起来
>>> 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() # 注意隐藏了的函数属性,obj,就不会再提示出来,只会提示withdraw这个函数,因此操作简单明了,如果提示一大堆,看着头都晕
本质就是为了明确地区分内外,隐藏数据属性,是为了保护数据,隐藏函数是为了屏蔽复杂的细节。类内部可以修改封装内的东西而不影响外部调用者的代码
;而类外部只需拿到一个接口,只要接口名、参数不变,则无论设计者如何改变内部实现代码,使用者均无需改变代码。这就提供一个良好的合作基础,只要接口这个基础约定不变,则代码的修改不足为虑。4、property
提供了一个装饰器property,可以将类中的函数“伪装成”对象的数据属性
,对象在访问该特殊属性时会触发功能的执行,然后将返回值作为本次访问的结果,例如>>> 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**2) ... >>> obj=People('lili',75,1.85) >>> obj.bmi #触发方法bmi的执行,将obj自动传给self,执行后返回值作为本次引用的结果 21.913805697589478
>>> class Foo: ... def __init__(self,val): ... self.__NAME=val #将属性隐藏起来 ... @property ... def name(self): ... return self.__NAME ... @name.setter ... def name(self,value): ... if not isinstance(value,str): #在设定值之前进行类型检查 ... raise TypeError('%s must be str' %value) ... self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME ... @name.deleter ... def name(self): ... raise PermissionError('Can not delete') ... >>> f=Foo('lili') >>> f.name lili >>> f.name='LiLi' #触发name.setter装饰器对应的函数name(f,’Egon') >>> f.name=123 #触发name.setter对应的的函数name(f,123),抛出异常TypeError >>> del f.name #触发name.deleter对应的函数name(f),抛出异常PermissionError
不让用户肆无忌惮的对属性操作
,但是提供函数供用户使用
,使其对属性进行修改、查看、删除,这样不符合用户的使用习惯
,因此,我们需要用上面的方法,使其符合用户的使用习惯,且限制规范了用户对属性的操作
注意:最后送大家一套2020最新企业Pyhon项目实战视频教程,点击此处 进来获取 跟着练习下,希望大家一起进步哦!
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算