day25 类的组合、多态和封装

昨日回顾:
-继承
-如何使用
-通过继承来减少代码冗余
-如何重用父类的方法一
-属性查找顺序
-如何重用父类的方法二
-派生
今日内容:
-组合
-什么时候用组合,什么时候用继承
-什么是什么的关系用继承
-什么有什么的关系用组合
-多态和多态性

​ -封装

一、组合

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

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

bar = Bar()
f = Foo(bar)

# 为什么使用组合: 可以减少代码冗余
class Person:
    school = 'old_boy'

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

class Course:
    def __init__(self, course_name, course_price):
        self.course_name = course_name
        self.course_price = course_price

course = Course('Python', 20000)
stu = Student('nick', course)
teacher = Teacher('nick', '高级', course)

print(stu.course.name)
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))

二、多态与多态性

什么是多态:一类事物的多种形态

多态性:多态性是指在不考虑实例类型的情况下使用实例

好处: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()

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

# 两种约束代码的方式
# 第一种:用abc模块实现接口统一化,约束代码(用的比较少)
# 第二种:用异常处理来实现(常用)
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)

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

三、封装

封装是什么:封装就好像是拿来一个麻袋,把小猫,小狗,小王八,一起装进麻袋,然后把麻袋封上口子,然后隐藏起来,外部访问不到。

如何用代码实现隐藏:

​ 隐藏属性/隐藏方法,隐藏之后,外部访问不到,只有内部能访问

​ # 隐藏属性: 通过 __变量名来隐藏

​ # 隐藏方法: 通过 __方法名来隐藏

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

p = Person('nick', 89)
print(p.age)
print(p.get_name())
# 通过变形隐藏了属性
# 隐藏的属性在python还是能够在外部访问,但是一般不这么做
print(p.__Person__name)
print(p.__dict__)

# 隐藏方法:隔离复杂度
class Person:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age
        
    def __speak(self):
        print('wangwang')
        
p = Person('nick', 89)
p.__speak()
print(Person.__dict__)
P._Person__speak()

# 什么时候属性变形,只要在类内部,以__变量名 命名的变量,都会被隐藏,会发生变形,在外部放  # 入的__变量名 属性是不会隐藏的

# 计算人的bmi指数
# 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.hetght ** 2)
    
p = Person('lqz', 1.82, 70)
print(p.bmi)

# 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 = 999
p.name = 'sb_nick'

猜你喜欢

转载自www.cnblogs.com/17vv/p/11425736.html
今日推荐