zoukankan      html  css  js  c++  java
  • 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()
    不让子类覆盖父类的同名属性
  • 相关阅读:
    机器学习粗略认识--线性模型
    LDA主题模型困惑度计算
    python-igraph
    pandas 使用技巧
    pandas读取MySql/SqlServer数据
    聚类模型性能评价指标
    各种编码格式
    利用分块传输吊打所有WAF--学习笔记
    Sql 注入----学习笔记2
    Sql 注入----学习笔记
  • 原文地址:https://www.cnblogs.com/guodengjian/p/8823930.html
Copyright © 2011-2022 走看看