小猿圈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算出来跟深度优先效果一样)。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容

  • 初识面向对象 楔子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战>的游戏,你就思考呀,人狗作战...
    go以恒阅读 914评论 0 6
  • 写在前面的话 代码中的# > 表示的是输出结果 输入 使用input()函数 用法 注意input函数输出的均是字...
    FlyingLittlePG阅读 2,734评论 0 8
  • 一.继承介绍 1 什么是继承 继承一种新建类的方式,新建的类称之为子类/派生类,被继承的类称之为父类\基类\超...
    aq_wzj阅读 311评论 0 0
  • 对象间的交互 在游戏中有很多玩家,他们互砍,如何实现的? 还记得我们开头的引子么,人狗大战,用面向对象如何实现? ...
    小猿圈IT教育阅读 708评论 0 1
  • 一、封装【private】 1.概念 广义的封装:函数和类的定义本身,就是封装的体现狭义的封装:一个类的某些属性,...
    hollow_02f9阅读 1,397评论 0 3