Python 面向对象 组合-多态与多态

发布时间:2019-03-02 10:49:08编辑:auto阅读(1983)

    面向对象-组合

    1.什么是组合

      组合指的是某一个对象拥有一个属性,该属性的值是另外一个类的对象

     1 class Foo:
     2     xxx = 111
     3 
     4 class Bar:
     5     yyy = 222
     6 
     7 obj = Foo()
     8 obj.attr = Bar()
     9 
    10 print(obj.xxx)
    11 >>>111
    12 print(obj.attr.yyy)
    13 >>>222

     

    2.为何要用组合

      通过为某一个对象添加属性(属性的值是另外一个类的对象)的方式,可以间接地将两个类关联/整合/组合到一起

      从而减少类与类之间代码冗余

     1 class Foo1:
     2     pass
     3 class Foo2:
     4     pass
     5 class Foo3:
     6     pass
     7 
     8 class Bar:
     9     pass
    10 
    11 obj_from_bar=Bar()
    12 
    13 obj1=Foo1()
    14 obj2=Foo2()
    15 obj3=Foo3()
    16 
    17 obj1.attr1=obj_from_bar
    18 obj2.attr2=obj_from_bar
    19 obj3.attr3=obj_from_bar

     

    3.如何用组合

     1 class OldboyPeople:
     2     school = 'Oldboy'
     3 
     4     def __init__(self, name, age, sex, ):
     5         self.name = name
     6         self.age = age
     7         self.sex = sex
     8 
     9 
    10 class OldboyStudent(OldboyPeople):
    11     def __init__(self, name, age, sex, score=0):
    12         OldboyPeople.__init__(self, name, age, sex)
    13         self.score = score
    14         self.courses = []
    15 
    16     def choose_course(self):
    17         print('%s choosing course' % self.name)
    18 
    19     def tell_all_course(self):
    20         print(('学生[%s]选修的课程如下' % self.name).center(50, '='))
    21         for obj in self.courses:
    22             obj.tell_info()
    23         print('=' * 60)
    24 
    25 
    26 class OldboyTeacher(OldboyPeople):
    27     def __init__(self, name, age, sex, level):
    28         OldboyPeople.__init__(self, name, age, sex)
    29         self.level = level
    30         self.courses = []
    31 
    32     def score(self, stu, num):
    33         stu.score = num
    34 
    35     def tell_all_course(self):
    36         print(('老师[%s]教授的课程如下' % self.name).center(50, '*'))
    37         for obj in self.courses:
    38             obj.tell_info()
    39         print('*' * 70)
    40 
    41 
    42 class Course:
    43     def __init__(self, c_name, c_price, c_period):
    44         self.c_name = c_name
    45         self.c_price = c_price
    46         self.c_period = c_period
    47 
    48     def tell_info(self):
    49         print('<课程名:%s 价钱:%s 周期:%s>' % (self.c_name, self.c_price, self.c_period))
    50 
    51 
    52 # 创建课程对象
    53 python = Course('python全栈开发', 1900, '5mons')
    54 linux = Course('linux架构师', 900, '3mons')
    55 
    56 stu1 = OldboyStudent('刘二蛋', 38, 'male')
    57 stu1.courses.append(python)
    58 stu1.courses.append(linux)
    59 stu1.tell_all_course()
    60 
    61 tea1 = OldboyTeacher('egon', 18, 'male', 10)
    62 tea1.courses.append(python)
    63 tea1.tell_all_course()

     

    面向对象-多态与多态性

    1.什么是多态

      多态指的是同一种/类事物的不同形态

    2.为何要用多态

      多态性:在多态的背景下,可以在不用考虑对象具体类型的前提下而直接使用对象

    3.如何用多态

      Animal()  #父类只是用来建立规范的,不能用来实例化,更无需实现内部的方法

     1 import abc
     2 
     3 
     4 class Animal(metaclass=abc.ABCMeta):
     5     @abc.abstractmethod
     6     def speak(self):
     7         pass
     8 
     9     @abc.abstractmethod
    10     def run(self):
    11         pass
    12 
    13 
    14 
    15 class People(Animal):
    16     def speak(self):
    17         print('say hello')
    18 
    19     def run(self):
    20         pass
    21 
    22 
    23 class Dog(Animal):
    24     def speak(self):
    25         print('汪汪汪')
    26 
    27     def run(self):
    28         pass
    29 
    30 
    31 class Pig(Animal):
    32     def speak(self):
    33         print('哼哼哼')
    34 
    35     def run(self):
    36         pass
    37 
    38 
    39 obj1 = People()
    40 obj2 = Dog()
    41 obj3 = Pig()

    Python推崇的是鸭子类型,只要你叫的声音像鸭子,并且你走路的样子也像鸭子,那你就是鸭子

     1 class Disk:
     2     def read(self):
     3         print('Disk read')
     4 
     5     def write(self):
     6         print('Disk write')
     7 
     8 
     9 class Memory:
    10     def read(self):
    11         print('Mem read')
    12 
    13     def write(self):
    14         print('Mem write')
    15 
    16 
    17 class Cpu:
    18     def read(self):
    19         print('Cpu read')
    20 
    21     def write(self):
    22         print('Cpu write')
    23 
    24 
    25 obj1 = Disk()
    26 obj2 = Memory()
    27 obj3 = Cpu()
    28 
    29 obj1.read()
    30 obj2.read()
    31 obj3.read()

     

    面向对象-封装

    1.什么是封装

      装: 往容器/名称空间里存入名字

      封: 代表将存放于名称空间中的名字给藏起来,这种隐藏对外不对内

    2.为何要封装

      封装数据属性:

        将数据属性隐藏起来,类外就无法直接操作属性,需要类内部开辟一个接口,让外部的使用可以间接地操作属性,可以在接口内定制任意的控制逻辑,从而严格控制使用者对属性的操作

     1 class People:
     2     def __init__(self, name, age):
     3         self.__name = name
     4         self.__age = age
     5 
     6     def tell_info(self):
     7         print('<name:%s age:%s>' % (self.__name, self.__age))
     8 
     9     def set_info(self, name, age):
    10         if type(name) is not str:
    11             print('名字必须是str类型傻叉')
    12             return
    13         if type(age) is not int:
    14             print('年龄必须是int类型傻叉')
    15             return
    16         self.__name = name
    17         self.__age = age
    18 
    19 
    20 obj = People('egon', 18)
    21 obj.set_info('EGON', '18')
    22 obj.tell_info()

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

     1 class ATM:
     2     def __card(self):
     3         print('插卡')
     4 
     5     def __auth(self):
     6         print('用户认证')
     7 
     8     def __input(self):
     9         print('输入取款金额')
    10 
    11     def __print_bill(self):
    12         print('打印账单')
    13 
    14     def __take_money(self):
    15         print('取款')
    16 
    17     def withdraw(self):
    18         self.__card()
    19         self.__auth()
    20         self.__input()
    21         self.__print_bill()
    22         self.__take_money()
    23 
    24 
    25 a = ATM()
    26 a.withdraw()

    3.如何封装

      在类内定义的属性前加__开头(没有__结尾)

      总结:

        1. __开头的属性实现的隐藏仅仅只是一种语法意义上的变形,并不会真的限制类外部的访问

        2. 该变形操作只在类定义阶段检测语法时发生一次,类定义阶段之后新增的__开头的属性并不会变形

        3. 如果父类不想让子类覆盖自己的属性,可以在属性前加__开头

     1 class Foo:
     2     def __f1(self):  # _Foo__f1
     3         print('Foo.f1')
     4 
     5     def f2(self):
     6         print('Foo.f2')
     7         self.__f1()  # obj._Foo__f1()
     8 
     9 
    10 class Bar(Foo):
    11     def __f1(self):  # _Bar__f1
    12         print('Bar.f1')
    13 
    14 
    15 obj = Bar()
    16 
    17 >>>Foo.f2
    18 >>>Foo.f1

     

    面向对象-property

    property装饰器是用来将类内的函数属性伪装成数据属性

     1 class People:
     2     def __init__(self, name):
     3         self.__name = name
     4 
     5     @property
     6     def name(self):
     7         return '<名字:%s>' % self.__name
     8 
     9     @name.setter
    10     def name(self, obj):
    11         if type(obj) is not str:
    12             print('name必须为str类型')
    13             return
    14         self.__name = obj
    15 
    16     @name.deleter
    17     def name(self):
    18         print('不让删')
    19 
    20 obj = People('egon')
    21 del obj.name
    22 print(obj.__dict__)

     

关键字

上一篇: 多态与多态性

下一篇: Flask-Mail