面向对象三大特性之继承(面向对象的继承有几种)

网友投稿 906 2022-09-10

面向对象三大特性之继承(面向对象的继承有几种)

面向对象三大特性之继承(面向对象的继承有几种)

一、继承初体验

什么是继承

继承是一种新建类的方式,新建的类称之为子类或派生类,继承的父类称之为基类或超类。

- 在Python中,一个子类可以继承多个父类。(面试可能会问)

- 在其它语言中,一个子类只能继承一个父类。

继承的作用

减少代码冗余

如何实现继承法?

1) 先确认谁是子类,谁是父类。

2) 在定义类子类时, 子类名(父类名)。

小例子

#父类

class Father1:

x = 1

pass

class Father2:

pass

class Father3:

pass

#子类

class sub(Father1,Father2,Father3):

pass

#子类.__bases__查看父类

print(sub.__bases__)

#(, , )

print(sub.x)

#1

二、如何寻找继承关系

如何寻找继承关系

- 确认谁是子类

- 小小明对象 ---> 人子类 ---> 动物父类

- 猪坚强对象 ---> 猪子类 ---> 动物父类

- 哈士奇对象 ---> 狗子类 ---> 动物父类

- 人、猪、狗 都是子类

- 确认谁是父类

- 动物类是父类

- 得先抽象,再继承

- 抽取对象之间相似的部分,总结出类

- 抽取类之间相似的部分,总结出父类。

传统写法,代码冗余

#老师类

class Teacher:

school = 'oldboy'

country = 'china'

def __init__(self, name, age, sex):

self.name = name

self.age = age

self.sex = sex

#老师改分

def change_limit(self):

print(f'老师{self.name}开始批改分数...')

#学生类

class Student:

school = 'oldboy'

country = 'china'

def __init__(self, name, age, sex):

self.name = name

self.age = age

self.sex = sex

#学生选课

def choose_course(self, name, age, sex):

self.name = name

self.age = age

self.sex = sex

tea1 = Teacher('tank', 28, 'male')

print(tea1.name, tea1.age, tea1.sex) #tank 28 male

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

print(stu1.name, stu1.age, stu1.sex) #yafeng 18 male

'''这样写虽然也可以拿到我想要的信息,但是代码很长,且有很多代码重复,下面的父类就是解决这种情况'''

用父类去书写,解决代码冗余

#父类

class OldPeople:

school = 'oldboy'

country = 'china'

def __init__(self, name, age, sex):

self.name = name

self.age = age

self.sex = sex

#子类

#学生类

class OldStudent(OldPeople):

def chose_course(self):

print(f'学生{self.name}正在选课!')

#老师类

class OldTeacher(OldPeople):

def change_score(self):

print(f'老师{self.name}正在修改分数')

obj1 = OldStudent('yafeng', 18, 'male')

print(obj1.name, obj1.age, obj1.sex) #yafeng 18 male

obj2 = OldTeacher('tank', 25, 'male')

print(obj2.name, obj2.age, obj2.sex) #tank 25 male

三、在继承属性下对象属性的查找属性

注意

'''

注意: 程序的执行顺序是由上到下,父类必须定义在子类的上方。

- 在继承背景下,对象属性的查找顺序:

1.先从对象自己的名称空间中查找

2.对象中没有,从子类的名称空间中查找。

3.子类中没有, 从父类的名称空间中查找,若父类没有,则会报错!

'''

查找顺序演示

#父类

class Father:

x = 10

pass

#子类

class Sub(Father):

x = 100

pass

obj1 = Sub()

# print(obj1.x) #100 先从对象自己的名称空间中查找

# print(obj1.x) #10,此时把x=100注释掉,对象中没有,从子类的名称空间中查找。

# print(obj1.x) #将父类的x=10也注释掉AttributeError: 'Sub' object has no attribute 'x'

#注意:

obj1.x = 1000#这是给对象添加属性的操作,并不是修改子类的属性

print('子类的名称空间', Sub.__dict__)

#子类的名称空间 {'__module__': '__main__', 'x': 100, '__doc__': None}

print('对象的名称空间', obj1.__dict__)

#对象的名称空间 {'x': 1000}

print('父类的名称空间', Father.__dict__)

#父类的名称空间 {'__module__': '__main__', 'x': 10, '__dict__': ,

# '__weakref__': , '__doc__': None}

四、派生

派生

'''

派生:

指的是子类继承父类的属性与方法,并且派生出自己独有的属性与方法。

若子类中的方法名与父类的相同,优先用子类的。

'''

# #父类

# class Foo:

# def f1(self):

# print('from Foo.f1...')

#

# def f2(self):

# print('from Foo.f2...')

#

#

# #子类

# class Goo(Foo):

#

# #重写(其实python中根本没有重写一说,姑且就称之为重写)

# def f1(self):

# print('from Goo.f1...')

#

#

# def func(self):

# print('from Goo.func...')

#

# obj = Goo()

# print(obj.f1()) #from Goo.f1...

# print(obj.f2()) #from Foo.f2...

# print(obj.func()) #from Goo.func...

#父类

class Foo:

def f1(self):

print('from Foo.f1...')

def f2(self):

print('from Foo.f2...')

self.f1()

#子类

class Goo(Foo):

#重写(其实python中根本没有重写一说,姑且就称之为重写)

def f1(self):

print('from Goo.f1...')

def func(self):

print('from Goo.func...')

obj = Goo()

obj.f2() #答案是多少?

#'from Foo.f2...' 'from Goo.f1...'

五、子类继承父类并重用父类的属性的方法

代码

'''

- 子类继承父类,派生出自己的属性与方法,并且重用父类的属性与方法。

'''

'''需求:此时要给子类老师类添加新的属性薪水,给子类中的学生类添加女票'''

#方法一:直接在子类中添加ps(那我还要你父类干嘛)

#父类

# class OldPeople:

# school = 'oldboy'

# country = 'china'

#

# def __init__(self, name, age, sex):

# self.name = name

# self.age = age

# self.sex = sex

#

#

# #子类

# #学生类

# class OldStudent(OldPeople):

#

# def __init__(self, name, age, sex, girl_friend):

# self.name = name

# self.age = age

# self.sex = sex

# self.girl_friend = girl_friend

#

# def chose_course(self):

# print(f'学生{self.name}正在选课!')

#

#

# #老师类

# class OldTeacher(OldPeople):

#

# def __init__(self, name, age, sex, sal):

# self.name = name

# self.age = age

# self.sex = sex

# self.sal = sal

#

# def change_score(self):

# print(f'老师{self.name}正在修改分数')

#

#

#

# obj1 = OldStudent('yafeng', 18, 'male', '热巴')

# print(obj1.name, obj1.age, obj1.sex, obj1.girl_friend) #yafeng 18 male 热巴

#

#

# obj2 = OldTeacher('tank', 25, 'male', 15000)

# print(obj2.name, obj2.age, obj2.sex, obj2.sal) #tank 25 male 15000

'''

解决需求: 子类重用父类的属性,并派生出新的属性。

两种方式:

1.直接引用父类的__init__为其传参,并添加子类的属性。

2.通过super来指向父类的属性。

- super()是一个特殊的类,调用super得到一个对象,该对象指向父类的名称空间。

注意: 使用哪一种都可以,但不能两种方式混合使用。

'''

#方式一:直接引用父类的__init__为其传参,并添加子类的属性。

# #父类

# class OldPeople:

# school = 'oldboy'

# country = 'china'

#

# def __init__(self, name, age, sex):

# self.name = name

# self.age = age

# self.sex = sex

#

# #子类

# #学生类

# class OldStudent(OldPeople):

#

# def __init__(self, name, age, sex, girl_friend):

#

# # 类调用类内部的__init__,只是一个普通函数

# OldPeople.__init__(self, name, age, sex)

# self.girl_friend = girl_friend

#

# def chose_course(self):

# print(f'学生{self.name}正在选课!')

#

#

# #老师类

# class OldTeacher(OldPeople):

#

# def __init__(self, name, age, sex, sal):

# OldPeople.__init__(self, name, age, sex)

# self.sal= sal

#

# def change_score(self):

# print(f'老师{self.name}正在修改分数')

#

# obj1 = OldStudent('yafeng', 18, 'male', '热巴')

# print(obj1.name, obj1.age, obj1.sex, obj1.girl_friend) #yafeng 18 male 热巴

#

#

# obj2 = OldTeacher('tank', 25, 'male', 15000)

# print(obj2.name, obj2.age, obj2.sex, obj2.sal) #tank 25 male 15000

#方式二:2.通过super来指向父类的属性。

#- super()是一个特殊的类,调用super得到一个对象,该对象指向父类的名称空间。

# 父类

class OldPeople:

school = 'oldboy'

country = 'china'

def __init__(self, name, age, sex):

self.name = name

self.age = age

self.sex = sex

#子类

#学生类

class OldStudent(OldPeople):

def __init__(self, name, age, sex, girl_friend):

super().__init__(name, age, sex)#注意此时使用super()方法,不用传self

self.girl_friend = girl_friend

def chose_course(self):

print(f'学生{self.name}正在选课!')

#老师类

class OldTeacher(OldPeople):

def __init__(self, name, age, sex, sal):

super().__init__(name, age, sex)

self.sal = sal

def change_score(self):

print(f'老师{self.name}正在修改分数')

obj1 = OldStudent('yafeng', 18, 'male', '热巴')

print(obj1.name, obj1.age, obj1.sex, obj1.girl_friend) #yafeng 18 male 热巴

obj2 = OldTeacher('tank', 25, 'male', 15000)

print(obj2.name, obj2.age, obj2.sex, obj2.sal) #tank 25 male 15000

六、经典类与新式类

了解

#!/usr/bin/u/ubv/a python

#_*_ coding:utf8 _*_

'''

经典类与新式类: (了解)

- 工作中遇不到

- 面试有可能会问

- 新式类:

1.凡是继承object的类或子孙类都是新式类。

2.在python3中所有的类都默认继承object。

- 经典类:

1.在python2中才会有经典类与新式类之分。

2.在python2中,凡是没有继承object的类,都是经典类。

'''

class User(object):

pass

class User():

x = 10

pass

class Sub(User):

pass

print(User.__dict__)

七、super严格遵循mro继承顺序原则

了解

'''

调用mro返回的是一个继承序列: (了解知识点)

super的继承顺序严格遵循mro继承序列。

'''

class Father1:

x = 10

pass

class Father2:

x = 100

pass

class Sub(Father1, Father2):

pass

print(Sub.mro()) #[, , , ]

obj = Sub()

print(obj.x) #10

'''

在python3中提供了一个查找新式类查找顺序的内置方法.

mro(): 会把当前类的继承关系列出来。

'''

# 注意: super()会严格按照mro列表的顺序往后查找

class A:

def test(self):

print('from A.test')

super().test()

class B:

def test(self):

print('from B.test')

class C(A, B):

pass

c = C()

# 检查super的继承顺序

print(C.mro())

# # 去A找,有的话打印,然后super又执行了test,根据mro中查找打印B类中test。

# '''

# from A.test

# from B.test

# '''

八、钻石继承(菱形继承)

了解

'''

多继承情况下造成 “钻石继承”

mro的查找顺序:

- 新式类:

- 广度优先

- 经典类:

- 深度优先

面试注意细节:

- 遇到一个技术 知道是什么,但是不会用,一定要贬低这个技术,觉得很简单,让面试官误以为你很会。

- 遇到一个技术,不知道是什么,要说我见过,但是忘记怎么用了,我博客里面,回头找一下就行了。

-新式类:广度优先

- 经典类:深度优先

'''

# 了解:

# 新式类:

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())

obj = F()

obj.test()

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:powershell获取所有的.net类型快捷访问方式
下一篇:Android.mk 包含问题带来的so.toc needed by 错误
相关文章

 发表评论

暂时没有评论,来抢沙发吧~