小猿圈python学习-三大特性之继承

面向对象的继承
比较官方的说法就是:

继承(英语:inheritance)是面向对象软件技术当中的一个概念。如果一个类别A“继承自”另一个类别B,

就把这个A称为“B的子类别”,而把B称为“A的父类别”也可以称“B是A的超类”。

继承可以使得子类别具有父类别的各种属性和方法,而不需要再次编写相同的代码。

在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,

即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。另外,为子类别追加新的属性和方法也是常见的做法。 一般静态的面向对象编程语言,继承属于静态的,意即在子类别的行为在编译期就已经决定,无法在执行期扩充。

字面意思就是:子承父业,合法继承家产,就是如果你是独生子,而且你也很孝顺,不出意外,

你会继承你父母所有家产,他们的所有财产都会由你使用(败家子儿除外)。

继承与抽象(先抽象再继承)
抽象即抽取类似或者说比较像的部分。

抽象分成两个层次:

1.将雷昂纳多和王思聪这俩对象比较像的部分抽取成类;

2.将人,猪,狗这三个类比较像的部分抽取成父类。

抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度)

继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。

抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类

class Animal:
def init(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
class People(Animal):
def walk(self):
print(“People [%s] is walking…” % self.name)
class Pig(Animal):
def eat(self):
print(“Pig [%s] is eating…” % self.name)
class Dog(Animal):
def eat(self):
print(“Dog [%s] is eating…” % self.name)
person = People(“Alex”,25,“Male”)
pig = Pig(“Mjj”,4,“公”)
dog = Dog(“毛毛”,3,“母”)
person.walk()
pig.eat()
dog.eat()
继承的有点也是显而易见的:

1,增加了类的耦合性。

2,减少了重复代码。

3,使得代码更加规范化,合理化。

继承的分类
就向上面的例子:

Aminal 叫做父类,基类,超类。

Person Pig Dog: 子类,派生类。

继承:可以分单继承,多继承。

继承父类的方法&重构
class Animal:
def init(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def eat(self):
print("[%s] is eating…"%self.name)
class People(Animal):
def walk(self):
print(“People [%s] is walking…” % self.name)
class Pig(Animal):
def eat(self): # 对父类的方法进行了重构
print(“Pig [%s] is eating…” % self.name)
person = People(“Alex”,25,“Male”)
pig = Pig(“Mjj”,4,“公”)
person.walk()
person.eat() # 继承自父类的eat方法
pig.eat()
同时执行子类&父类方法
方法一:
如果想执行父类的init方法,这个方法并且子类中也用,那么就在子类的方法中写上:
父类.func(子类对象,其他参数)

class Animal:
def init(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def eat(self):
print("[%s] is eating…"%self.name)
class People(Animal):
def init(self,name,age,sex,race):
Animal.init(self,name,age,sex) # 先执行父类方法
self.race = race # 再加上子类的属性
print(“初始化了一个人…”)
def walk(self):
print(“People [%s] is walking…” % self.name)
方法二:
利用super,super().func(参数)

class People(Animal):
def init(self,name,age,sex,race):
#Animal.init(self,name,age,sex) # 先执行父类方法
super(People,self).init(name,age,sex)
#super().init(name,age,sex) # 跟上面这行super语法的效果一样,一般用这种写法的多
self.race = race # 再加上子类的属性
print(“初始化了一个人…”)

多继承Multiple Inheritance
class ShenXian:
“”“神仙类”""
def fly(self):
print(“神仙都会飞…”)
class Monkey:
def eat_peach(self):
print(“猴子都喜欢吃桃子…”)
class MonkeyKing(ShenXian,Monkey):
def play_goden_stick(self):
print(“孙悟空玩金箍棒…”)
sxz = MonkeyKing()
sxz.eat_peach()
sxz.fly()
sxz.play_goden_stick()
此时, 孙悟空是一只猴子, 同时也是一个神仙. 那孙悟空继承了这两个类.

孙悟空自然就可以执行这两个类中的方法. 多继承用起来简单. 也很好理解.

假如在继承的多个类里出现了重名的方法怎么办呢? 如下:

class ShenXian:
“”“神仙类”""
def fly(self):
print(“神仙都会飞…”)
def fight(self):
print(“神仙在打架…”)
class Monkey:
def eat_peach(self):
print(“猴子都喜欢吃桃子…”)
def fight(self):
print(“猴子在打架…”)
class MonkeyKing(ShenXian,Monkey):
def play_goden_stick(self):
print(“孙悟空玩金箍棒…”)
sxz = MonkeyKing()

sxz.eat_peach()

sxz.fly()

sxz.play_goden_stick()

sxz.fight()
调用sxz.fight()你说会打印哪个呢?

根据执行结果,我们得知,多继承的顺序是按参数 MonkeyKing(ShenXian,Monkey)从左到右,不信你可以自己换一下位置试试。

真的是从左到右么? 如果继承的父类又继承爷爷类,并且还重名了呢?

class ShenXianBase:
def fight(self):
print(“神仙祖宗在打架…”)
class MonkeyBase:
def fight(self):
print(“猿猴在打架…”)
class ShenXian(ShenXianBase):
“”“神仙类”""
def fly(self):
print(“神仙都会飞…”)
#def fight(self):
# print(“神仙在打架…”)
class Monkey(MonkeyBase):
def eat_peach(self):
print(“猴子都喜欢吃桃子…”)
def fight(self):
print(“猴子在打架…”)
class MonkeyKing(ShenXian,Monkey):
def play_goden_stick(self):
print(“孙悟空玩金箍棒…”)
sxz = MonkeyKing()
sxz.fight()
此时,若把ShenXian类里的fight注释掉,你说sxz.fight()会打印哪个? 是引用Monkey里的fight呢,还是ShenXianBase里的fight呢?

输出:
神仙祖宗在打架…
这个查找顺序是按什么规则呢?

在Python 中,有2种类的写法, 不同写法的采用的继承顺序不同

class A: # 经典类
pass
class B(object): # 新式类
pass
在python 2中,经典类采用的是深度优先查找法, 新式类采用的是广度优先

在python 3中,无论是经典类,还是新式类,都是按广度优先查找

Python 2.x中默认都是经典类,只有显式继承了object才是新式类

Python 3.x中默认都是新式类,不必显式的继承object

*之所以在python3中全改成了广度优先,是因为用深度优先在某些特殊情况下,会出现bug.

啊啊啊??? 上面演示的明明不是按深度优先继承的么? 你现在说py3用的都是广度,这不是睁眼说瞎话么?
多继承原理之C3算法
亲,我没说瞎话,在下面这种条件下,你发现继承的顺序你可能都理解不了了。

class A:
def test(self):
print(‘from A’)
class B(A):
# def test(self):
# print(‘from B’)
pass
class B2:
def test(self):
print(‘from B2’)
class C(A):
def test(self):
print(‘from C’)
class C2:
def test(self):
print(‘from C2’)
class D(B,B2):
# def test(self):
# print(‘from D’)
pass
class E(C,C2):
def test(self):
print(‘from E’)
class F(D,E):
# def test(self):
# print(‘from F’)
pass
f1=F()
f1.test()
print(F.mro) # 打印类的继承顺序
输出:
from E
(, , , , , , , , )
为了帮你理清继承顺序,我画了图

你发现,这好像即不是按深度优先,也不是按广度优先呀。 看着没什么规律呀。 其实是有规律的,是按一个叫C3算法来计算继承顺序的。
这个C3算法呢,对现阶段的你,估计不太好理解,所以我也不打算讲, 不过确实也不太重要。 因为很少有人把继承写的这么复杂。 你以后常遇到的也就像下图这种水平的了,

像这种,你就按深度优先来找顺序就可以(因为像这种简单的多继承,c3算出来跟深度优先效果一样)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值