zoukankan      html  css  js  c++  java
  • day 25 类的组合、多太与多态性、封装

    组合
    什么是组合:对象的某个属性是另一个类的对象

    #组合的概念
    class Foo:
    def __init__(self,bar):
    self.bar=bar

    class Bar:
    pass

    # f=Foo()
    bar=Bar()
    # f=Foo(Bar())
    f=Foo(bar)

    为什么使用组合:可以减少代码冗余

    class Person:
      school = 'oldboy'
    class Teacher(Person):
    def __init__(self,name,age,level,course_name,course_price,course_period):
    self.name=name
    self.age=age
    self.level=level

    class Student(Person):
    def __init__(self,name,age,course,course_name,course_price,course_period):
    self.name=name
    self.age=age
    self.course=course


    #通过组合解决代码冗余
    class Person:
    school = 'oldboy'

    class Teacher(Person):
    def __init__(self,name,age,level,course):
    self.name=name
    self.age=age
    self.level=level
    #course是课程对象,表示老师教授的课程
    self.course=course

    class Student(Person):
    def __init__(self,name,age,course):
    self.name=name
    self.age=age
    # course是课程对象,表示学生选的课程
    self.course = course

    class Course:
    def __init__(self,course_name,course_price,course_period):
    self.name=course_name
    self.price=course_price
    self.period=course_period

    course=Course('Python',20180,7)
    stu=Student('nick',19,course)
    teacher=Teacher('nick',19,'高级',course)
    #查看老师教授的课程名
    print(teacher.course.name)


    如何使用组合
    class Person:
    school = 'oldboy'
    class Teacher(Person):
    def __init__(self,name,age,level,course):
    self.name=name
    self.age=age
    self.level=level
    #course是课程对象,表示老师教授的课程
    self.course=course

    class Student(Person):
    # course=[] #错误
    def __init__(self,name,age):
    self.name=name
    self.age=age
    # course是课程对象,表示学生选的课程
    self.course_list = []
    def choose_course(self,course):
    # self.course=[] #错误
    #把课程对象追加到学生选课的列表中
    self.course_list.append(course)

    def tell_all_course(self):
    #循环学生选课列表,每次拿出一个课程对象
    for course in self.course_list:
    #课程对象.name 取到课程名字
    print(course.name)

    class Course:
    def __init__(self,course_name,course_price,course_period):
    self.name=course_name
    self.price=course_price
    self.period=course_period


    course=Course('Python',20199,7)
    stu1=Student('nick',19)
    stu1.choose_course(course)
    stu2=Student('王二丫',19)
    stu2.choose_course(course)
    stu2.choose_course(Course('linux',19999,5))


    查看stu1选的所有课程名称
    方式一(通过普通函数)
    def tell_all_course(student):
    for course in student.course_list:
    print(course.name)

    tell_all_course(stu1)
    tell_all_course(stu2)

    方式二(通过对象的绑定方法)
    stu1.tell_all_course()
    stu2.tell_all_course()




    多态与多态性
    多态性:多态性是指在不考虑实例类型的情况下使用实例
    好处:
    1.增加了程序的灵活性
    2.增加了程序额可扩展性

    多态基础
    class Animal:
    def speak(self):
    pass

    class Pig(Animal):
    def speak(self):
    print('哼哼哼')

    class Dog(Animal):
    def speak(self):
    print('汪汪')

    class People(Animal):
    def speak(self):
    print('say hello')

    pig=Pig()
    dog=Dog()
    people=People()
    # pig.speak()
    # dog.speak()
    # people.speak()

    def animal_speak(obj):
    obj.speak()
    animal_speak(pig)
    animal_speak(people)


    # def len(obj):
    # return obj.__len__()
    # len('xxxx')
    # len([1,2,3])
    '''
    第一种方式:用abc实现接口统一化,约束代码(用的比较少)
    import abc
    #第一在括号中写metaclass=abc.ABCMeta
    class Animal(metaclass=abc.ABCMeta):
    #第二在要约束的方法上,写abc.abstractmethod装饰器
    @abc.abstractmethod
    def speak(self):
    pass

    class Pig(Animal):
    def speak(self):
    print('哼哼哼')
    class Dog(Animal):
    def yy(self):
    print('汪汪')

    class People(Animal):
    def zz(self):
    print('say hello')


    people = People()
    people.zz()
    #方法名不一致,就不能利用多态性
    def animal_speak(obj):
    obj.speak()
    pig=Pig()

    第二种方式,用异常处理来实现(常用)
    class Animal():
    def speak(self):
    #主动抛出异常
    raise Exception('你得给我重写它啊')
    class Pig(Animal):
    def speak(self):
    print('哼哼哼')
    class People(Animal):
    def speak(self):
    print('say hello')
    pig=Pig()
    pe=People()

    def animal_speak(obj):
    obj.speak()
    animal_speak(pig)
    animal_speak(pe)

    崇尚鸭子类型:只要走路像鸭子(对象中有某个绑定方法),那你就是鸭子

    class Pig:
    def speak(self):
    print('哼哼哼')
    class People:
    def speak(self):
    print('say hello')

    pig=Pig()
    pe=People()
    def animal_speak(obj):
    obj.speak()
    animal_speak(pig)
    animal_speak(pe)

    linux 一切皆文件
    #传统写法
    class File:
    def read(self):
    pass
    def write(self):
    pass
    #内存类
    class Memory(File):
    def read(self):
    print('Memory...read')
    def write(self):
    print('Memory...write')

    class Network(File):
    def read(self):
    print('Network...read')
    def write(self):
    print('Network...write')
    #鸭子类型的写法

    内存类
    class Memory:
    def read(self):
    print('Memory...read')

    def write(self):
    print('Memory...write')

    class Network:
    def read(self):
    print('Network...read')

    def write(self):
    print('Network...write')

    def read(obj):
    obj.read()
    m=Memory()
    n=Network()
    read(m)
    read(n)



    封装
    把东西包装进去之后,隐藏起来,外部访问不到
    如何用代码实现隐藏
    隐藏属性/隐藏方法 隐藏之后,外部访问不到,只有内部能够访问
    隐藏属性:通过 __变量名来隐藏
    隐藏方法:通过 __方法名来隐藏

    name 隐藏起来
    #隐藏属性是为了安全
    class Person:
    def __init__(self,name,age):
    self.__name=name
    self.__age=age
    def get_name(self):
    print(self.__name)
    return '[----%s-----]'%self.__name

    p=Person('nick',89)
    print(p.age)
    访问name
    print(p.name)
    print(p.__name)
    print(p.get_name())
    隐藏的属性访问不到?实际上有方法能访问到
    通过变形隐藏了属性
    print(p._Person__name)

    print(p.__dict__)


    #隐藏方法:隔离复杂度
    class Person:
    def __init__(self,name,age):
    self.__name=name
    self.__age=age
    def __speak(self):
    print('6666')

    p=Person('nick',89)
    p.__speak()
    print(Person.__dict__)
    p._Person__speak()

    什么时候属性变形,只要再类内部,以__变量名 命名的变量,都会被隐藏,会发生的变形,在外部放入的 __变量名 属性是不隐藏的
    class Person:
    def __init__(self,name,age):
    self.__name=name
    self.__age=age
    def set_xx(self,xx):
    self.__xx=xx

    p=Person('nick',18)
    # ._P_xx="xxx"

    p.set_xx('6688')
    print(p.__dict__)

    #property装饰器:把方法包装成数据属性
    class Person:
    def __init__(self,name,height,weight):
    self.name=name
    self.height=height
    self.weight=weight
    @property
    def bmi(self):
    return self.weight/(self.height**2)
    # return self.weight/(self.height*self.height)
    p=Person('lqz',1.82,70)
    # print(p.bmi())
    print(p.bmi)
    # p.name='ppp'
    p.bmi=90


    #property之setter和deleter
    class Person:
    def __init__(self,name,height,weight):
    self.__name=name
    self.__height=height
    self.__weight=weight
    @property
    def name(self):
    return '[我的名字是:%s]'%self.__name
    #用property装饰的方法名.setter
    @name.setter
    def name(self,new_name):
    # if not isinstance(new_name,str):
    if type(new_name) is not str:
    raise Exception('改不了')
    if new_name.startswith('sb'):
    raise Exception('不能以sb开头')
    self.__name=new_name

    # 用property装饰的方法名.deleter
    @name.deleter
    def name(self):
    # raise Exception('不能删')
    print('删除成功')
    # del self.__name

    p=Person('lqz',1.82,70)
    print(p.name)
    p.name='pppp'
    p.name='xxx'
    改不了,直接抛一异常
    p.name=999
    p.name='sb_nick'

    print(p.name)

    del p.name
    print(p.name)


    
    





  • 相关阅读:
    NOIP初赛知识点大全-普及+提高组
    cron表达式详解,cron表达式写法,cron表达式例子
    n2n的编译和运行、配置
    Visual Studio 2017 扩展
    iis url重写
    http重定向到https
    基于git命令的代码统计方法
    UseSwagger
    docker中mysql数据库的数据导入和导出
    Win10远程桌面提示你的凭据不工作的处理方法
  • 原文地址:https://www.cnblogs.com/wwei4332/p/11424695.html
Copyright © 2011-2022 走看看