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
多态与鸭子类型
鸭子类型:当几个类中有相同的方法时,可以将这些相同的功能提取出来放到一个新的类中,然后让他们都继承这个新的类

浙公网安备 33010602011771号