目录
- 今日内容概要
- 内容详细
- 封装
- 继承(概念)
- 继承实例
- 单继承下的属性查找
- 多继承下的属性查找
- super()和mro列表
- 多态和多态性(了解)
- 内容详细
今日内容概要
- 面向对象的三大特征
- 封装
- 继承(重要)
- 多态
- 继承的属性查找顺序
- 单继承下的属性查找
- 多继承下的属性查找
- super()和mro()列表
- 多态与多态性(了解)
内容详细
封装
# 将功能封装成函数
# 在类中 我们正常定义的方法 就是封装
继承(概念)
1.什么是继承
'''
继承就是新建类的一种方式 新建的类我们称之为 子类 或者 派生类
被继承的类称之为 父类 或者 基类
子类可以使用父类中的属性或方法
'''
2.为什么要用继承
'''
类解决了对象与对象之间的代码冗余问题
继承解决的是类与类之间的代码冗余问题
'''
3.如何使用继承
# 新式类
继承了object类的子子孙孙类
# 经典类
没有继承object类的子子孙孙类
'''
新式类和经典类只在python2中区分
python3只有新式类
'''
继承实例
# 以学生选课系统为例
# 定义父类
class People:
school = 'SH'
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
# 定义学生类(子类)
class Student(People): # 继承父类People
def __init__(self, name, age, gender, course=None):
if course is None:
course = []
People.__init__(self, name, age, gender)
self.courses = course
def choose_course(self, course):
self.courses.append(course)
print('%s 选课成功 %s' % (self.name, self.courses))
stu = Student('ly', 19, 'male')
print(stu.name) # ly
# 定义老师类(子类)
class Teacher(People): # 继承父类People
def __init__(self, name, age, gender, level):
self.level = level
People.__init__(self, name, age, gender)
def score(self, stu_obj, score):
stu_obj.score = score # 给学生打分
print('%s给%s打了%s分' % (self.name, stu_obj.name, score))
tea = Teacher('ly', 19, 'male', 10)
print(tea.name) # ly
print(tea.level) # 10
单继承下的属性查找
class Foo:
def f1(self):
print('Foo.f1')
def f2(self):
print('Foo.f2') # 1
self.f1() # self = obj = Bar 所以要找 Bar中的 f1
class Bar(Foo):
def f1(self):
print('Bar.f1') # 2
obj = Bar() # {}
print(Bar.mro()) # [, , ] 查找空间顺序
obj.f2()
'''
打印结果:
Foo.f2
Bar.f1
'''
# 练习
class Foo:
def __f1(self): # _Foo__f1()
print('Foo.f1')
def f2(self):
print('Foo.f2') # 1
self.__f1() # _Foo__f1() 此处的__f1是属于Foo类空间产生的f2对象空间中 所以结果是 Foo.f1
class Bar(Foo):
def __f1(self): # # _Bar__f1()
print('Bar.f1')
obj = Bar() # {}
print(Bar.mro()) # [, , ] 查找空间顺序
obj.f2()
'''
打印结果:
Foo.f2
Foo.f1
'''
多继承下的属性查找
# 新式类:按照广度优先查询(经典类:按照深度优先查询)
class A(object):
def test(self):
print('from A')
class B(A):
def test(self):
print('from B')
pass
class C(A):
def test(self):
print('from C')
pass
class D(B):
# def test(self):
# print('from D')
pass
class E(C):
# def test(self):
# print('from E')
pass
class F(D, E):
# def test(self):
# print('from F')
pass
f1 = F()
f1.test()
print(F.mro()) # 查找顺序按照 [, , , , , , ] 找不到就下一个类 不能返回查找
'''
打印结果:
from B
'''
super()和mro列表
# 父类
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):
if course is None:
course = []
# People.__init__(self, name, age, gender) # 指名道姓的调用父类的方法
# super(Student, self) 返回了一个特殊的对象
# 它的使用遵从mro列表
# super(Student, self).__init__(name, age, gender) # python2的写法
super().__init__(name, age, gender) # python3 的写法
self.courses = course
def choose_course(self, course):
self.courses.append(course)
print('%s 选课成功 %s' % (self.name, self.courses))
stu = Student('ly', 19, 'male')
print(stu.name) # ly
# 老师类(子类)
class Teacher(People):
def __init__(self, name, age, gender, level):
self.level = level
People.__init__(self, name, age, gender)
def score(self, stu_obj, score):
stu_obj.score = score # 给学生打分
print('%s给%s打了%s分' % (self.name, stu_obj.name, score))
tea = Teacher('ly', 19, 'male', 10)
print(tea.name) # ly
print(tea.level) # 10
# 例题1
class A:
def test(self):
print('from A.test')
super().test()
class B:
def test(self):
print('from B')
class C(A, B):
pass
c = C()
c.test()
print(C.__mro__) # 查找顺序 按照mro列表 由C3线性算法产生 (, , , )
'''
打印结果:
from A.test
from B
'''
# 例题2
class B:
def test(self):
print('B---->test')
def aaa(self):
print('B---->aaa')
class A:
def test(self):
print('A---->test')
super().aaa()
class C(A, B):
def aaa(self):
print('C----->aaa')
c = A()
c.test() # 打印结果: A---->test + 报错
print(A.mro()) # 查找顺序 [, ] A类找不到就直接报错
多态和多态性(了解)
1.什么是多态
水:
液态水 固态水 气态水
动物:
人 猪 狗 猫...
# 抽象类 定义
抽象类只能被继承 不能被实例化
# 固定语法
import abc
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod # 该方法已经是抽象方法了
def speak(self): pass
@abc.abstractmethod # 子类函数必须含有 login 方法 没有就会直接报错
def login(self): pass
class People(Animal):
def speak(self):
print('嗷嗷嗷')
def login(self): # 子类函数必须含有 login 方法 没有就会直接报错
pass
'''
如果定义抽象类了 那么子类当中必须由抽象类的方法名
即使子类函数体代码为pass也可
否则将直接报错 而不会再到抽象类(父类)查找
eg:
class People(Animal):
def jiao(self):
print('嗷嗷嗷')
obj = People()
obj.speak()
打印结果:
直接报错
'''
class Pig(Animal):
def speak(self):
print('哼哼哼')
class Dog(Animal):
def speak(self):
print('汪汪汪')
obj = People()
obj.speak()
'''
打印结果:
嗷嗷嗷
'''
# 在python3中 抽象类写法墨守成规为以下
# 省去了abc模块固定语法
class People():
def speak(self):
print('嗷嗷嗷')
class Pig():
def speak(self):
print('哼哼哼')
class Dog():
def speak(self):
print('汪汪汪')
class Txt():
def speak(self):
print('Txt')
obj = People()
obj1 = Pig()
obj2 = Dog()
obj3 = Txt()
# 多态带来的特性:在不用考虑对象数据类型的情况下,直接调用对应的函数 封装成函数调用
def animal(animal):
return animal.speak()
animal(obj)
animal(obj1)
animal(obj2)
animal(obj3)
# len 就是多态一种场景
len('abc')
len([1, 2, 3])
len({'username': 'ly'})
def len(item):
return item.__len__()
print(len('abc'))
# 父类限制子类的行为(抽象类) 还可以用异常捕获主动报错
class Animal():
def speak(self):
raise Exception("必须实现speak方法") # 主动报错出去
class People(Animal):
pass
class Pig():
def speak(self):
print('哼哼哼')
class Dog():
def speak(self):
print('汪汪汪')
obj = People()
obj.speak()
# 一切皆文件 只要类中含有read,write方法 就看做文件类
class Txt:
def read(self):
pass
def write(self):
pass
class Process():
def read(self):
pass
def write(self):
pass