• Python之旅.第五章.面向对象


    一、组合

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

    1、继承:描述的是类与类之间,什么是什么的关系

    2、组合:描述的是类与类之间的关系,是一种什么有什么关系;一个类产生的对象,该对象拥有一个属性,这个属性的值是来自于另外一个类的对象

    #组合不属于继承

    #类的使用将变量及处理其的函数捆绑起来

    #继承是强耦合,组合是解耦合

     

    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)

     

    stu1=Oldboystudent('张三',16,'male','linux')

    stu1.birth=Date(2002,3,3)

    stu1.birth.tell_birth()

     

    二、组合练习

    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()

     

    三、如何封装以及封装的目的

    1、什么是封装:

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

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

     

    2、如何用封装

    如何把属性隐藏起来,就在属性前面加上__开头(注意不要加__结尾)

    注意:

    a、其实这种隐藏只是一种语法上的变形,对外不对内

    为一个属性名加__开头(注意不要加__结尾),会在类定义阶段将属性名统一变形:_自己的类名__属性名

     

    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)

     

    obj=Foo(22222)

    print(obj.x)

    print(obj.__x)

    obj.__f1()

    print(obj.y)

    print(obj.__y)

    print(Foo.__dict__)

    print(obj._Foo__x)

    print(obj._Foo__y)

    obj._Foo__f1()

    obj.get_y()

     

    b、这种语法意义上变形,只在类定义阶段发生一次,类定义之后,新增的__开头的属性都没有变形的效果

     

    Foo.__aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=1

    print(Foo.__dict__)

     

    obj.__bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb=2

    print(obj.__dict__)

     

    c、如果父类不想让子类覆盖自己的方法,可以在方法名前加__开头

    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()

     

    3、为什么要用封装

    a、封装数据属性的目的:把数据属性封装起来,然后需要开辟接口给类外部的使用者使用,好处是我们可以在接口之上添加控制逻辑,从而严格空间访问者对属性的操作

    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')

     

    b、封装函数属性的目的:为了隔离复杂度

     

    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()s

     

    c、封装的终极奥义:明确地区分内外,对外是隐藏的,对内是开放的

  • 相关阅读:
    js设计模式 -- 拷贝模式
    超简单的SpringBoot整合mybatis
    使用JS调用手机本地摄像头或者相册图片识别二维码/条形码
    SpringBootsad整合EhCache做缓存处理
    调用微信的扫一扫功能详解说明---(java 排坑版)
    获取系统文件的创建日期
    在windows上获取文件创建时间
    简单计算器
    lambda-基于谓词筛选值序列
    IEnumerable<T>和IQueryable<T>区别
  • 原文地址:https://www.cnblogs.com/yangli0504/p/8849242.html
Copyright © 2020-2023  润新知