面向对象——继承
面向对象——继承
什么是继承?
- 继承是一种新建类的方式,新建的类称之为子类或派生类,继承的父类称之为基类或超类。
# 父类
class Father1:
x = 1
pass
class Father2:
pass
class Father3:
pass
# 子类
class Sub(Father1, Father2, Father3):
pass
# 子类.__bases__ 查看父类
print(Sub.__bases__)
print(Sub.x)
# 打印结果:
# (<class '__main__.Father1'>, <class '__main__.Father2'>, <class '__main__.Father3'>)
# 1
继承的作用?
- 继承可以减少代码的冗余
# 老师类
class OldboyTeacher:
school = 'oldboy'
country = 'China'
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
# 老师修改分数
def change_score(self):
print(f'老师 {self.name} 正在修改分数...')
# 学生类
class OldboyStudent:
school = 'oldboy'
country = 'China'
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
# 学生选择课程
def choose_course(self):
print(f'学生 {self.name} 正在选择课程...')
stu1 = OldboyStudent('YJG', 50, 'female')
print(stu1.school, stu1.name, stu1.age, stu1.sex)
tea1 = OldboyTeacher('tank', 17, 'male')
print(tea1.school, tea1.name, tea1.age, tea1.sex)
# 这里我们会发现上面代码会有很多重复的地方,下面我们就用继承
# 定义父类People
class People:
school = "老男孩"
country = "China"
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
# 老师类
class OldboyTercher(People):
def change_score(self):
print(f"老师{self.name}正在修改分数")
# 学生类
class OldboyStudent(People):
def choose_course(self):
print(f"学生{self.name}正在选择课程")
stu1 = OldboyStudent("张三", 18, "男")
print(stu1.name, stu1.age, stu1.sex)
tea1 = OldboyTercher("tank", 20, "男")
print(tea1.name, tea1.age, tea1.sex)
如何实现继承?
- 先确认谁是子类谁是父类
- 在定义子类时 子类名(父类名)
怎么查看子类继承的那个父类?
子类.__ bases __
注意:在python中一个子类可以继承多个父类,其他语言中一个子类只有一个父类
如何寻找继承关系?
- 确认谁是子类
- 确认谁是父类
在继承背景下,对象属性的查找顺序
1、先从对象自己的名称空间查找
2、对象中没有,从子类名称空间查找
3、子类名称空间没有,从父类名称空间查找,没有就报错
# 父类
class Goo:
x = 10
pass
# 子类
class Foo(Goo):
x = 100
pass
foo_obj = Foo()
foo_obj.x = 1000
print(foo_obj.x)
print('对象的名称空间: ', foo_obj.__dict__)
print('子类的名称空间: ', Foo.__dict__)
print('父类的名称空间: ', Goo.__dict__)
# 打印结果
# 对象的名称空间: {'x': 1000}
# 子类的名称空间: {'__module__': '__main__', 'x': 100, '__doc__': None}
# 父类的名称空间: {'__module__': '__main__', 'x': 10, '__dict__': <attribute '__dict__' of 'Goo' objects>, '__weakref__': <attribute '__weakref__' of 'Goo' objects>, '__doc__': None}
就如下图:
派生
-
派生指的是子类继承父类的属性和方法,并衍生出自己独有的属性和方法,这种情况就是派生。
需要注意的是,当子类的名字和父类相同时,会优先使用子类的名字。
# 父类
class Foo:
def f1(self):
print("from Foo.f1....")
def f2(self):
print("from Foo.f2....")
self.f1()
# 子类
class Bar(Foo):
def f1(self):
print("from Bar.f1....")
def func(self):
print("from Bar.func....")
bar_obj = Bar()
bar_obj.f1()
bar_obj.func()
bar_obj.f2()
# 打印结果:
# from Bar.f1....
# from Bar.func....
# from Foo.f2....
# from Bar.f1....
子类继承父类,派生出自己的属性与方法,并且重用父类的属性与方法
怎么用呢?
1、直接引用父类的__ init __为其传参,并添加子类的属性
2、通过super来指向父类的属性
super()是一个特殊的类,调用super得到一个对象,该对象指向父类的名称空间
注意:这两种方式使用哪一种都可以,但不可以混合使用
# 方式一 __init__()方法
class People:
school = "oldboy"
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
class OldboyTeacher(People):
def __init__(self, name, age, sex, sal):
People.__init__(self, name, age, sex)
self.sal = sal
def change_score(self):
print(f"老师{self.name}修改分数...")
class OldboyStudent(People):
def __init__(self, name, age, sex, girl):
People.__init__(self, name, age, sex)
self.girl = girl
def choose_course(self):
print(f"学生{self.name}选择课程...")
tea1 = OldboyTeacher("tank", 18, "男", 150000)
print(tea1.name, tea1.age, tea1.sex, tea1.sal)
stu1 = OldboyStudent("张全蛋", 20, "男", "凤姐")
print(stu1.name, stu1.age, stu1.sex, stu1.girl)
# 方式二 super()方法
class People:
school = "oldboy"
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
class OldboyTeacher(People):
def __init__(self, name, age, sex, sal):
super().__init__(name, age, sex)
self.sal = sal
def change_score(self):
print(f"老师{self.name}修改分数...")
class OldboyStudent(People):
def __init__(self, name, age, sex, girl):
super().__init__(name, age, sex)
self.girl = girl
def choose_course(self):
print(f"学生{self.name}选择课程")
tea1 = OldboyTeacher("tank", 25, "男", 15000)
print(tea1.name, tea1.age, tea1.sex, tea1.sal)
stu1 = OldboyStudent("张全蛋", 18, "男", "凤姐")
print(stu1.name, stu1.age, stu1.sex, stu1.girl)
这里提一嘴经典类与新式类的知识(了解)
新式类
1、python2中凡是继承object的类或子孙类都是新式类
2、python3中所有的类都默认继承object
经典类
1、python2中凡是没有继承object的类都是经典类
2、python3中没有经典类
在python3中提供了一个查找新式类查找顺序的内置方法
mro():会把当前类的继承关系列出来
多继承情况下造成"钻石继承"(菱形继承)
mro查找顺序:
新式类:广度优先
经典类:深度优先
# 新式类:
# 这里只说新式类,博主电脑没装python2
class A(object):
def test(self):
print('from A')
pass
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
# F-->D-->B-->E-->C-->A-->object
print(F.mro())
# 打印结果:
# [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]