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                # 报错
  • 相关阅读:
    HDU 1010 Tempter of the Bone
    HDU 4421 Bit Magic(奇葩式解法)
    HDU 2614 Beat 深搜DFS
    HDU 1495 非常可乐 BFS 搜索
    Road to Cinema
    Sea Battle
    Interview with Oleg
    Spotlights
    Substring
    Dominating Patterns
  • 原文地址:https://www.cnblogs.com/mylu/p/11135203.html
Copyright © 2011-2022 走看看