29---面向对象特性--继承

一 property 装饰器

  • 引入---计算BMI指数
class People:
    def __init__(self,name,weight,height):
        self.name = name
        self.weight = weight
        self.height = height
    def bmi(self):
        self.bmi = self.weight/(self.height**2)
        return self.bmi
people = People('gui',51,1.67)
print(people.bmi())
# 按照人类的思维来想,bmi应该是数据属性,不是函数属性,所以为了让人能够按照人的思维去使用,作为设计者应该在程序内部进行设计,让使用者认为bmi就是数据属性
  • property:装饰器,用来将绑定给对象的函数属性伪装成一个数据属性
    
class People:

    def __init__(self,name,weight,height):
        self.name = name
        self.weight = weight
        self.height = height

    @property
    def bmi(self):
        return self.weight / (self.height ** 2)

people = People('gui',51,1.67)
print(people.bmi)
  • property的其他用法
class People:
    def __init__(self,name):
        self.__name = name

    def get_name(self):
        print(self.__name)

    def set_name(self,new_name):
        if type(new_name) is str:
            self.__name = new_name
            print(self.__name)
        else:
            print('需要字符串格式')

    def del_name(self):
        print('不允许删除')
    name = property(get_name,set_name,del_name)
people = People('gui')
people.name # 人类思维:people.name
people.name = 123  # 人类的思维 people.name = new_name
del people.name # 人类的思维del people.name
  • 对案例二进一步优化
# 案例三
class People:
    def __init__(self,name):
        self.__name = name
    @property
    def name(self):
        return self.__name
    @name.setter
    def name(self,new_name):
        self.__name = new_name
    @name.deleter
    def name(self):
        print('不能删除')
people = People('haha')
print(people.name)
people.name = 'gui'
print(people.name)
del people.name

二 继承与派生

  • 什么是继承
1 什么是继承
继承是一种创建新类的方式,新建的类可称为子类或者派生类,父类又可称为基类或者超类,子类会遗传弗雷的属性
python支持多继承,新建的类可以继承一个或多个父类
class Parent1:
    x = 111
class Parent2:
    pass
class Sub(Parent1): # 单继承
    pass
class Sun(Parent1,Parent2): # 多继承
    pass
# __bases__查看子类继承的所有的父类
print(Sub.__bases__)
print(Sun.__bases__)
注意:
在python2中有新式类和经典类之分
新式类:继承了object的子类,以及该子类的子类、子子类...
经典类:没有继承object类的子类,以及该子类的子类、子子类 

在python3中没有继承任何类,那么会默认继承object类,所以在python3中所有的类都是新式类
2 为何要用继承
用来解决类与类之间的代码重复问题
3 如何实现继承
  • 继承引入
class Student:
    school = 'old_boy'
    def __init(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

    def choose(self):
        print(f'{self.name}正在选课')
class Teacher:
    school = 'old_boy'

    def __init__(self, name, age, sex,salary,level):
        self.name = name
        self.age = age
        self.sex = sex
        self.salary = salary
        self.level = level
    def score(self):
        print(f'{self.name}正在打分')
# 以上代码出现重复的问题
# 基于继承解决上述两个类的代码重复问题
class OldPeople:
    school = 'old_boy'
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex
# 创建学生子类
# 派生的第一种:直接继承父类的属性
class Student(OldPeople):
    def choice(self):
        print(f'{self.name}正在选课')
# # 创建老师子类
# # 派生的第二种:覆盖父类属性
class Teacher:
    school = 'old_boy'

    def __init__(self, name, age, sex,salary,level):
        self.name = name
        self.age = age
        self.sex = sex
        self.salary = salary
        self.level = level
    def score(self):
        print(f'{self.name}正在打分')
# 老师类还是有重复的代码
# 派生的第三种:指名道姓跟父类要__init__
class Teacher(OldPeople):
    school = 'old_boy'

    def __init__(self, name, age, sex,salary,level):
        OldPeople.__init__(self,name,age,sex)
        self.salary = salary
        self.level = level
    def score(self):
        print(f'{self.name}正在打分')


tea = Teacher('hah',12,'male',100,10)
print(tea.__dict__)

三 多继承

  • 菱形问题介绍与mro
菱形继承:不同子类拥有同一个非object的父类,而不同的子类又是另一个子类的父类
class A:
    def test(self):
        print('from A')
class B(A):
    def test(self):
        print('from B')
class C(A):
    def test(self):
        print('from C')
class D(B,C):
    def test(self):
        print('from D')
# 类D及类D的对象访问属性都是参照该类的mro列表
print(D.mro())
总结:类相关的属性查找(类名.属性,该类的对象.属性),都是参照该类的mro
  • 多继承-----非菱形继承
如果多继承是非菱形继承,经典类与新式的属性查找顺序一样:都是一个分支一个分支地找下去,然后最后找object
  • 多继承----菱形继承
如果多继承是菱形继承,经典类与新式类的属性查找顺序不一样:

# 经典类:深度优先,会在检索第一条分支的时候就直接一条道走到黑,即会检索大脑袋(共同的父类)

# 新式类:广度优先,会在检索最后一条分支的时候检索大脑袋
# 总结:
# 多继承到底要不用???
# 要用,但是规避几点问题
# 1、继承结构尽量不要过于复杂
# 2、推荐使用mixins机制:在多继承的背景下满足继承的什么"是"什么的关系
posted @ 2020-04-09 22:00  微信搜索-程序媛小庄  阅读(144)  评论(0编辑  收藏  举报