python基础 -28- 面向对象(封装-Inheritance)

介绍

 比较官方的说法就是:

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

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

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

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

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

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

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


继承与抽象(先抽象再继承)

 抽象即抽取类似或者说比较像的部分。

 抽象分成两个层次:

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

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

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

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

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


class Animal:
    type = "哺乳动物"

    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 Person(Animal):
    # 重写属性
    type = "人"

    def __init__(self, name, age, sex, hobbie):
        # 调用父类的构造器
        # Animal.__init__(self, name, age, sex)
        super(Person, self).__init__(name, age, sex)
        self.hobbie = hobbie

    def talk(self):
        print(Person.type, " %s is talking" % self.name)

    # 重写方法
    def eat(self):
        # 调用父类的方法
        super().eat()
        print(Animal.type, "person %s is  eating gracefully" % self.name)

class Dog(Animal):

    def chase_rabbit(self):
        print(Dog.type, "-狗追兔子")

p = Person("老八", 25, "M", ["打篮球", "踢足球"])
p.eat()
p.talk()

print("-----")
d = Dog("小黑", 5, "Female")
d.eat()
d.chase_rabbit()

 输出

老八 is eating...
哺乳动物 person 老八 is  eating gracefully
人  老八 is talking
-----
小黑 is eating...
哺乳动物 -狗追兔子

多继承
class Fairy:
    """神仙类"""

    def __init__(self, name):
        self.name = name

    def fly(self):
        print("神仙都会飞...")

    def fight(self):
        print("神仙打架...")

class Monkey:
    """猴子类"""

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def eat_peach(self):
        print("猴子都喜欢吃桃子...")

    def fight(self):
        print("猴子打架...")

class MonkeyKing(Fairy,Monkey):
    """
     孙悟空
    """

    def play_goden_stick(self):
        super().fight()  # 调用Fairy中的方法
        print(self.name, "玩棒子...")

m = MonkeyKing("孙猴子")
m.fly()
m.eat_peach()
m.play_goden_stick()
# 调用父类的方法
m.fight()

 输出

神仙都会飞...
猴子都喜欢吃桃子...
神仙打架...
孙猴子 玩棒子...
神仙打架...

可以看到,子类调用的都是父类Fairy中的方法,说明了什么???


具体调用关系
说明

途中显示的调用的关系是按深度优先来调用的。以下为具体分析(不是最终结论)

第一个(G)
class A:
    def desc(self):
        print("A")

class B:
    def desc(self):
        print("B")

class C:
    def desc(self):
        print("C")

class D:
    def desc(self):
        print("D")

class E(A,B):
    def desc(self):
        print("E,继承自A和B")

class F(C,D):
    def desc(self):
        print("F,继承自C和D")


class G(E, F):
    def desc(self):
        print("G,继承自E和F")

g = G()
g.desc()

 输出

G,继承自E和F
第二个(E)
class A:
    def desc(self):
        print("A")

class B:
    def desc(self):
        print("B")

class C:
    def desc(self):
        print("C")

class D:
    def desc(self):
        print("D")


class E(A,B):
    def desc(self):
        print("E,继承自A和B")

class F(C,D):
    def desc(self):
        print("F,继承自C和D")


class G(E, F):
    
    
        pass

g = G()
g.desc()

emsp;输出

E,继承自A和B

第三个(A)
class A:
    def desc(self):
        print("A")

class B:
    def desc(self):
        print("B")

class C:
    def desc(self):
        print("C")

class D:
    def desc(self):
        print("D")


class E(A,B):
    
        pass

class F(C,D):
    def desc(self):
        print("F,继承自C和D")


class G(E, F):
    
        pass

g = G()
g.desc()

 输出

A

第四个(B)
class A:
    
        pass

class B:
    def desc(self):
        print("B")

class C:
    def desc(self):
        print("C")

class D:
    def desc(self):
        print("D")


class E(A,B):
    
        pass

class F(C,D):
    def desc(self):
        print("F,继承自C和D")


class G(E, F):
    
        pass

g = G()
g.desc()

 输出

B

第五个(F)
class A:
    
        pass

class B:
    
        pass

class C:
    def desc(self):
        print("C")

class D:
    def desc(self):
        print("D")


class E(A,B):
    
        pass

class F(C,D):
    def desc(self):
        print("F,继承自C和D")


class G(E, F):
    
        pass

g = G()
g.desc()

 输出

F,继承自C和D

第六个©
第七个(D)

结论

在python 2中,经典类采用的是深度优先查找法, 新式类采用的是广度优先

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

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

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

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

啊啊啊??? 上面演示的明明不是按深度优先继承的么? 你现在说py3用的都是广度,这不是睁眼说瞎话么?其实严格来说也并不是完全的广度优先,而是使用了C3算法


多继承原理之C3算法
class Base:
    def desc(self):
        print("Base")


class A(Base):
    
        pass


class B(Base):
    def desc(self):
        print("B")

class C(Base):
    def desc(self):
        print("C")


class D:
    def desc(self):
        print("D")


class E(A,B):
        pass

class F(C,D):
    def desc(self):
        print("F,继承自C和D")


class G(E, F):
        pass

g = G()
g.desc()

 输出

B

去掉B继承的Base,再查看结果

class B:
    def desc(self):
        print("B")
        
-----
F,继承自C和D

此时调用的是F,B跳过了???

去掉F和C继承desc()方法,再查看结果

class C(Base):
     # def desc(self):
     #     print("C")
     
        pass

class F(C,D):
    # def desc(self):
    #     print("F,继承自C和D")
    
        pass

    
-----
Base

此时调用了Base

如果有一个公共继承类,只会先在继承了Base中的类进行深度优先查找,如果继承了Base的类都没有该方法,就会调用Base中的方法,如果Base中也没有,就会从非继承类中查找

上述的调用顺序(初始的代码)可以用G.mro()方法查看

[<class '__main__.G'>, <class '__main__.E'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.F'>, <class '__main__.C'>, <class '__main__.Base'>, <class '__main__.D'>, <class 'object'>]

 G->E->A->B->F->C->Base->D->obejct(object是因为py3中默认是新式类)


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值