zoukankan      html  css  js  c++  java
  • python 之 面向对象基础(组合和封装)

    7.4 组合

    解决类与类之间代码冗余问题有两种解决方案:

    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)
    ​
    ​
    tea1=OldboyTeacher('egon',18,'male',9,3.1)  #创建老师类的对象tea1
    date_obj=Date(2000,1,1)                    #创建Date类的对象date_obj
    date_obj.tell_birth()                      #date_obj可以调用绑定方法tell_birth
    ​
    tea1.birth=date_obj                        #tea1的birth属性来自于Date类的一个对象date_obj   
    tea1.birth.tell_birth()                     #tea1的birth属性可以调用tell_birth属性                    
    stu1=Oldboystudent('张三',16,'male','linux')
    stu1.birth=Date(2002,3,3)
    stu1.birth.tell_birth()
    stu1.choose()                               #使用stu1将两个类联系起来
    View Code

    7.5 封装

    什么是封装: 装就是把一堆属性存起来,封的概念就把这些属性给隐藏起来,其实这种隐藏只是一种语法上的变形,对外不对内

    注意:

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

    class Foo:
        x=1
        __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)               # 1          
    print(obj.__x)              # 报错
    print(obj._Foo__x)         # 1111
    ​
    obj.__f1()                 #报错
    obj._Foo__f1()             # Foo.f1
    print(obj.y)               #报错
    print(obj.__y)             #报错
    print(obj._Foo__y)         # 22222
    obj.get_y()                # 22222 明确地区分内外,对外是隐藏的,对内是开放的

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

    Foo.__aaa=1
    print(obj.__aaa) # 1

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

    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()    # Foo.f2 Foo.f1

    7.51 封装的作用

    封装数据属性的目的:

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

    class People:
        def __init__(self,name):
                self.__name=name
    ​
         def tell_name(self):
                    # 添加逻辑
                    return self.__name
                
     obj=People('egon')
     #obj.__name
     obj.tell_name()

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

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

    7.52 封装之property

    用来将类内的函数伪装成一个数据属性

    例:

    体质指数()体重()身高()

      首先需要明确 : bmi是算出来的,不是一个固定死的值,也就说我们必须编写一个功能,每次调用该功能 都会立即计算一个值

    class People:
        def __init__(self,name,weight,height):
            self.name=name
            self.weight=weight
            self.height=height
    ​
        @property           #于是我们需要为bmi这个函数添加装饰器,将其伪装成一个数据属性
        def bmi(self):
            return self.weight / (self.height * self.height)
        
    egon=People('egon',75,1.80)
    yl=People('yangli',85,1.74)
    # print(egon.bmi())
    # print(yl.bmi())
    print(egon.bmi)         # 21.604938271604937,调用egon.bmi本质就是触发函数bmi的执行,从而拿到其返回值
    print(yl.bmi)           # 把功能伪装成一个属性

    @name.setter 和 @name.deleter

    # egon.bmi=123 
    # egon.bmi背后对应的是一个函数,所以不能赋值
    class People:
        def __init__(self,name):
            self.__name=name
    ​
        @property
        def name(self): 
             # 添加逻辑
            return self.__name
    ​
        @name.setter
        def name(self,x):
             # 添加逻辑
            self.__name=x
    ​
        @name.deleter
        def name(self):
             # 添加逻辑
            del self.__name
    ​
    obj=People('egon')
    print(obj.name)  # egon
                           # 修改
    obj.name='EGON'         # 现在可以赋值
    print(obj.name)         # EGON
    del obj.name            # 删除
    ​
    obj.name                # 报错
  • 相关阅读:
    Start Developing iOS Apps (Swift) 开始开发iOS应用(Swift)
    ansible copy file
    多个sshkey 指定key来clone仓库
    elastic search 日期为string类型导致视图无法展示时间的解决办法
    ubuntu 安装php 报错解决
    ruby hash 默认值的问题
    11.Mysql 之MHA(高可用)
    10. 主从复制-主从复制(基于GTID)--附加半同步复制
    9 .mysql的备份与恢复
    11.Mysql之回表、最左匹配、索引下推
  • 原文地址:https://www.cnblogs.com/mylu/p/11135203.html
Copyright © 2011-2022 走看看