python之路--day21--组合与封装

Posted 木夂各

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python之路--day21--组合与封装相关的知识,希望对你有一定的参考价值。

讲在组合之前: 

  解决类和类之间代码冗余问题有两种解决方案:1,继承  2,组合

  1,继承:描述的是类和类之间,什么是什么的关系,一种从属关系

  2,组合:描述的是类和类之间的关系。是一种什么有什么的关系

组合:一个类产生的对象,该对象拥有一个属性,这个属性的值来自于另外一个类的对象

  

技术分享图片
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(......................)
class OldboyTeacher(OldboyPeople):
       def __init__(self,name,age,sex,course):
             super().__init__(name,age,sex)
             self.course = course
       def change_score(self):
            print(......................)


tea1 = OldboyTeacher(egon,18,male,9,3.1)
data_obj = Data(2000,1,1)

tea1.birth = data_obj
##
##
此处:为tea1对象新增了一个属性birth,这个属性的值是Data实例化的对象data_obj....这就是类的组合
##
##
类的组合
技术分享图片
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

        self.courses=[]

    def change_score(self):
        print(teacher %s is changing score %self.name)

    def tell_course_info(self):
        print((老师%s 教授的课程信息如下 %self.name).center(50,=))
        for course_obj in self.courses:
            course_obj.info()


class Oldboystudent(OldboyPeople):
    def __init__(self,name,age,sex):
        super().__init__(name,age,sex,)
        self.courses=[]

    def choose(self):
        print(student %s choose course %self.name)

    def tell_course_info(self):
        print((学生%s 学习的课程信息如下 % self.name).center(50, =))
        for course_obj in self.courses:
            course_obj.info()

class Course:
    def __init__(self,cname,period,price):
        self.cname=cname
        self.period=period
        self.price=price

    def info(self):
        print(课程信息<名字:%s 周期:%s  价钱:%s> %(self.cname,self.period,self.price))


tea1=OldboyTeacher(egon,18,male,9,3.1)
stu1=Oldboystudent(张三,16,male)

python=Course(Python全栈开发,5mons,3000)
linux=Course(Linux高级架构师,5mons,2000)
go=Course(Go开发工程师,3mons,1000)


# # 给老师添加课程
# tea1.courses.append(python)
# tea1.courses.append(linux)

# print(tea1.courses)
# tea1.courses[0].info()
# for course_obj in tea1.courses:
#     course_obj.info()

# tea1.tell_course_info()


# 给学生添加课程
stu1.courses.append(python)
stu1.courses.append(go)
stu1.courses.append(linux)
stu1.tell_course_info()
组合练习

 

封装:

  什么是封装:

    装就是把一堆属性存起来,封就是把这些属性给隐藏起来

    强调:封装单从字面意思看就等同于隐藏,但其实封装绝对不是单纯意义的隐藏

  为什么要用封装:

    最终目的:明确区分内外,对内部开发,对外部隐藏

    封装数据属性的目的:把数据属性封装起来,然后需要开辟接口给类外部的使用者使用。然后在接口上添加控制逻辑,

        从而严格控制访问者对属性的操作

        

技术分享图片
class People:
    def __init__(self,name,age):
        self.__name=name
        self.__age=age

    def tell_info(self):

            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
数据属性的封装

    封装函数属性的目的:隔离复杂度

 

技术分享图片
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()
函数属性的封装

 

  如何用封装

    在属性前面就是 __开头(一定注意不要加__结尾)

    特征:1,__开头隐藏属性,只是语法上的一种变形,对外不对内

        什么是对外不对内:为一个属性加__开头,会在类定义阶段将属性名统一变形为:_ 自己的类名__ 属性名

        

技术分享图片
class Foo:
    __x=1111             #_Foo__x=1111
    def __init__(self,y):
        self.__y=y         #self._Foo__y=y

    def __f1(self):         #_Foo__f1
        print(Foo.f1)

    def get_y(self):
        print(self.__y)     # print(self._Foo__y)            

#类内部在定义阶段全部做了语法上的修改,所以内部可以访问__开头的属性

#但是类外部无法直接通过属性名访问类内部属性    
__开头封装类属性

       2,这种语法上的变形,只在类定义阶段生效一次,定义阶段之后再定义的__开头的属性,没有隐藏的效果

技术分享图片
# Foo.__aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=1
# print(Foo.__dict__)

# obj.__bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb=2
# print(obj.__dict__)
类定义之后再定义的__开头

      3,如果父类不想子类覆盖掉自己的属性,可以在定义阶段在使用__开头,隐藏属性、

技术分享图片
class Foo:
    def __f1(self): #_Foo__f1
        print(Foo.f1)

    def f2(self):
        print(Foo.f2)
        self.__f1()    #obj._Foo__f1()

class Bar(Foo):
    def __f1(self): #_Bar__f1
        print("Bar.f1")

obj=Bar()

obj.f2()
不让子类覆盖父类的同名属性

 

以上是关于python之路--day21--组合与封装的主要内容,如果未能解决你的问题,请参考以下文章

Python之路,day8-Python基础

学习PYTHON之路, DAY 7 - PYTHON 基础 7 (面向对象基础)

Python20期课堂总结-20180120day7-面向对象之继承组合多态封装等

Python全栈之路Day21

Python之路Day21-自定义分页和cookie

Python之路,Day21 - 常用算法学习