python 15 面向对象的三大特性

day 15 面向对象的三大特性

一、封装

见day14

二、继承

1、什么是继承
继承是一种新建子类的方式,新建的类称之为子类/派生类,被继承的称之为父类/基类

子类会遗传父类的属性

2、为何要用继承
类是解决对象之间冗余问题的
继承可以解决类与类之间的冗余问题

3、如何继承
在python中支持多继承

在python3中如果一个类没有继承任何父类,那么默认继承object类

但凡是继承了object类的子类,以及该子类的子子孙孙类都能用到object内的功能,称之为新式类
没有继承object类的子类,以及该子类的子子孙孙类都不能用到object内的功能,称之为经典类

ps: 只有在python2中才区分经典类与新式类,python3中都是新式类
class ParentClass1:  # 定义父类
    pass


class ParentClass2:  # 定义父类
    pass


class SubClass1(ParentClass1):  # 单继承,基类是ParentClass1, 派生类是SubClass
    pass


class SubClass2(ParentClass1, ParentClass2):  # python支持多继承,用逗号分隔开多个继承的类
    pass


print(SubClass2.__bases__)
print(SubClass1.__bases__)
print(ParentClass2.__bases__)
# 在子类派生的新方法中如何重用父类的功能
# 方式一:指名道姓地访问父类的函数,与继承无关
# 方式二:super(),严格依赖继承

class People:
    school = 'SH'

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


class Student(People):
    def __init__(self, name, age, gender, course=None):
        People.__init__(self, name, age, gender)
        if course is None:
            course = []
        self.course = course

    def choose_course(self, course):
        self.course.append(course)
        print("学生%s, 选课成功 %s" % (self.name, self.course))


class Teacher(People):
    def __init__(self, name, age, gender, level):
        People.__init__(self, name, age, gender)
        self.level = level

    def score(self, stu_obj, num):
        stu_obj.num = num
        print('老师%s 为学生%s 打分%s' % (self.name, stu_obj.name, num))
        
        
        
class People:
    school = 'SH'

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


class Student(People):
    def __init__(self, name, age, gender, course=None):
        # People.__init__(self, name, age, gender)
        super().__init__(name, age, gender)
        if course is None:
            course = []
        self.course = course

    def choose_course(self, course):
        self.course.append(course)
        print("学生%s, 选课成功 %s" % (self.name, self.course))


class Teacher(People):
    def __init__(self, name, age, gender, level):
        # People.__init__(self, name, age, gender)
        super().__init__(name, age, gender)
        self.level = level

    def score(self, stu_obj, num):
        stu_obj.num = num
        print('老师%s 为学生%s 打分%s' % (self.name, stu_obj.name, num))


stu1 = Student('lem', 18, 'male')

tea1 = Teacher('emt', 28, 'female', 10)

print(stu1.__dict__)
print(tea1.__dict__)

单继承背景下的属性查找

class Foo:
    def f1(self):
        print('Foo.f1')

    def f2(self):
        print('Foo.f2')
        self.f1() 

class Bar(Foo):
    def f1(self): 
        print('Bar.f1')
 
obj = Bar()
obj.f2()
>>>>>>>>
Foo.f2
Bar.f1


class Foo:
    def __f1(self):  # _FOO__f1
        print('Foo.f1')

    def f2(self):
        print('Foo.f2')
        self.__f1()  # self._Foo__f1

class Bar(Foo):
    def __f1(self):  # _Bar__f1
        print('Bar.f1')

        
obj = Bar()
obj.f2()
>>>>>>>>
Foo.f2
Foo.f1

在多继承背景下的属性查找

# 在非菱形继承关系下,新式类与经典类的属性查找属性都一样,都是一个分支一个分支地找下去


# 菱形继承/死亡钻石:一个类继承的多条分支最终汇聚到一个非object类上
# 新式类:广度优先,最后找菱形继承的顶点类
# 经典类:深度优先,在第一条分支就回检索到菱形继承的顶点类

如何正确的使用多继承:mixins机制

分主类和从属类,主类往右放,从属类中不能有__init__方法,只需要有一些需要的功能

使用Mixin类实现多重继承要非常小心

  • 首先它必须表示某一种功能,而不是某个物品,python 对于mixin类的命名方式一般以 Mixin, able, ible 为后缀
  • 其次它必须责任单一,如果有多个功能,那就写多个Mixin类,一个类可以继承多个Mixin,为了保证遵循继承的“is-a”原则,只能继承一个标识其归属含义的父类
  • 然后,它不依赖于子类的实现
  • 最后,子类即便没有继承这个Mixin类,也照样可以工作,就是缺少了某个功能。(比如飞机照样可以载客,就是不能飞了)

组合

组合表达的关系:has-a

一个对象拥有一个属性,该属性值指向另外一个对象

class Foo:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def func1(self):
        print('from func1')


class Bar:
    def __init__(self, m, n):
        self.m = m
        self.n = n

    def func2(self):
        print('from func2')


obj1 = Foo(100, 200)
obj2 = Bar(111, 222)

obj2.xxx = obj1

obj2.func2()
obj2.xxx.func1()
===========>
from func2
from func1

三、多态

# 同一种事物有多种形态

# 多态性:
# 我们可以在不用知道对象具体类型的前提下,而直接使用对象


"abc".__len__()
[1, 2, 3].__len__()
{'a': 1, 'b': 2}.__len__()


# 内置方法len的定义
def len(obj):
    return obj.__len__()


print(len('abc'))
import abc

# 1.给子类定标准,让子类中不能有别的方法只能有父类中对应名字的方法
# 2.不能实例化
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def speak(self):
        pass

    def run(self):
        pass

多态与鸭子类型

鸭子类型:当几个类中有相同的方法时,可以将这些相同的功能提取出来放到一个新的类中,然后让他们都继承这个新的类

posted @ 2021-04-26 15:33  橘丶阳菜  阅读(59)  评论(0)    收藏  举报