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)


    
    





  • 相关阅读:
    [ERR] Node 10.211.55.8:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
    PAT A1137 Final Grading (25 分)——排序
    PAT A1136 A Delayed Palindrome (20 分)——回文,大整数
    PAT A1134 Vertex Cover (25 分)——图遍历
    PAT A1133 Splitting A Linked List (25 分)——链表
    PAT A1132 Cut Integer (20 分)——数学题
    PAT A1130 Infix Expression (25 分)——中序遍历
    PAT A1142 Maximal Clique (25 分)——图
    PAT A1141 PAT Ranking of Institutions (25 分)——排序,结构体初始化
    PAT A1140 Look-and-say Sequence (20 分)——数学题
  • 原文地址:https://www.cnblogs.com/wwei4332/p/11424695.html
Copyright © 2011-2022 走看看