面向对象之继承

天大地大妈咪最大 提交于 2019-11-25 21:01:40

面向对象之继承

什么是面向对象的继承?

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

为“B的子类别”,而把B称为“A的父类别”也可以称“B是A的超类”。继承可以使得子类别具有父类别的各种属性和方法,而

不需要再次编写相同的代码。在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的

原有属性和方法,使其获得与父类别不同的功能。另外,为子类别追加新的属性和方法也是常见的做法。 一般静态的面向

对象编程语言,继承属于静态的,意即在子类别的行为在编译期就已经决定,无法在执行期扩充。

class Person:
    def __init__(self,name,sex,age):
        self.name =name
        self.age = age
        self.sex = sex
class Cat:
    def __init__(self,name,sex,age):
        self.name = name
        self.sex =sex
        self.age =age
class Dog:
    def __init__(self,name,age,sex):
        self.name =name
        self.sex =sex
        self.age = age
# 定义三个不同的类
        
class Animal(object):
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age
# 定义一个Animal父类
class Person(Animal):
    pass
class Dog(Animal):
    pass
class Person(Animal):
    pass
# 派生三个子类

继承的优点:

  • 增加了类的耦合性(耦合性不宜多,宜精)。
  • 减少了重复代码。
  • 使得代码更加规范化,合理化。

继承的分类

父类,又叫基类,超类,上面例子中的Animal就是一个父类。

子类,派生类,由父类派生而成的类,可以调用父类的静态属性和动态方法。

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

经典类和新式类:

  • 在python2.2版本之前均为经典类,python2.2之后新式类和经典类并存,python3之后取消了经典类的概念、

  • 简单来说,在python2x基类的根如果什么也不写就是经典类,如果python的根为object就为新式类

  • python3x版本中只有一种类:

    python3中使⽤的都是新式类. 如果基类谁都不继承. 那这个类会默认继承 object

单继承

类名,对象执行父类方法

class Aniaml(object):
    type_name = '动物类'

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

    def eat(self):
        print(self)
        print('吃东西')


class Person(Aniaml):
    pass


class Cat(Aniaml):
    pass


class Dog(Aniaml):
    pass

# 类名:
print(Person.type_name)  # 可以调用父类的属性,方法。
Person.eat(111) 
print(Person.type_name)

执行顺序

class Animal(object):    # 1
    type_name = "动物类"   # 6
    def __init__(self,name,sex,age):  # 7
        self.name = name  # 8
        self.sex = sex   # 9
        self.age = age   # 10
    def eat(self):
        print(self)
        print("吃东西")
class Person(Animal):    # 2
    def eat(self):   # 11
        print("%s 吃饭"%self.name)  # 13
class Cat(Animal):      # 3
    pass
class Dog(Animal):      # 4
    pass
p1 = Person("alex","laygirl",34)   # 5
p1.eat()  #  12
# 结果:
alex 吃饭
# 实例化对象时必须执行__init__方法,类中没有,从父类找,父类没有,从object类中找。
# 先要执行自己类中的eat方法,自己类没有才能执行父类中的方法。

同时执行类以及父类中的方法

1.方法一:

如果想执行父类的func方法,这个方法并且子类中也用,那么就在子类的方法中写上:

父类.func(对象,其他参数)

class Aniaml(object):
    type_name = '动物类'
    def __init__(self,name,sex,age):
            self.name = name
            self.age = age
            self.sex = sex   # 继承父类中的三个静态属性

    def eat(self):
        print('吃东西')

class Person(Aniaml):
    def __init__(self,name,sex,age,mind):
        Aniaml.__init__(self,name,sex,age)  # 方法一
        self.mind = mind   # 封装mind属性

    def eat(self):
        super().eat()
        print('%s 吃饭'%self.name)
class Cat(Aniaml):
    pass

class Dog(Aniaml):
    pass
p1 = Person('春哥','laddboy',18,'有思想')
print(p1.__dict__)

2.利用super,super().func(参数)(父类的重构

class Animal:
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age
    def eat(self):
        print("动物都需要吃饭")
class Human(Animal):
    def __init__(self,name,sex,age,hobby):
        super(Human,self).__init__(name,sex,age)  # 继承父类中的三个静态属性
        self.hobby = hobby
    def eat(self):
        super().eat()  # 执行父类中的eat方法
        print(f"{self.name}都需要吃饭")
class Dog(Animal):
    pass
class Cat(Animal):
    pass
H1 = Human("小红","女",18,"看书")
H1.eat()
# 结果:
"动物都需要吃饭"
"小红都需要吃饭"

单继承经典练习题:

# 1
class Base:
    def __init__(self, num):
        self.num = num
    def func1(self):
        print(self.num)

class Foo(Base):
    pass
obj = Foo(123)
obj.func1() # 123 运⾏的是Base中的func1  

# 2      
class Base:
    def __init__(self, num):
        self.num = num
    def func1(self):
        print(self.num)
class Foo(Base):
    def func1(self):
        print("Foo. func1", self.num)
obj = Foo(123)
obj.func1() # Foo. func1 123 运⾏的是Foo中的func1       

# 3         
class Base:
    def __init__(self, num):
        self.num = num
    def func1(self):
        print(self.num)
class Foo(Base):
    def func1(self):
        print("Foo. func1", self.num)
obj = Foo(123)
obj.func1() # Foo. func1 123 运⾏的是Foo中的func1     
# 4
class Base:
    def __init__(self, num):
        self.num = num
    def func1(self):
        print(self.num)
        self.func2()
    def func2(self):
        print("Base.func2")
class Foo(Base):
    def func2(self):
    print("Foo.func2")
obj = Foo(123)
obj.func1() # 123 Foo.func2 func1是Base中的 func2是⼦类中的 
# 再来
class Base:
    def __init__(self, num):
        self.num = num
    def func1(self):
        print(self.num)
        self.func2()
    def func2(self):
        print(111, self.num)
class Foo(Base):
    def func2(self):
        print(222, self.num)
lst = [Base(1), Base(2), Foo(3)]
for obj in lst:
    obj.func2() # 111 1 | 111 2 | 222 3

# 再来
class Base:
    def __init__(self, num):
        self.num = num
    def func1(self):
        print(self.num)
        self.func2()
    def func2(self):
        print(111, self.num)
class Foo(Base):
    def func2(self):
        print(222, self.num)
lst = [Base(1), Base(2), Foo(3)]
for obj in lst:
 obj.func1() # 那笔来吧. 好好算

多继承

class A:
    def __init__(self,name):
        self.name = name
    def show_name(self):
        print(f"A的名字为{self.name}")
class B:
    def __init__(self,name):
        self.name = name
    def show_name(self):
        print(f"B的名字为{self.name}")
class C(A,B): # C同时继承A,B类
    pass
c = C("A")
print(c.name)
c.show_name()

在python这种,经典类和新式类继承父类所使用的算法是完全不同的

经典类的多继承

经典类的多继承采用深度优先算法

class A:
    pass
class B(A):
    pass
class C(A):
    pass
class D(B, C):
    pass
class E:
    pass
class F(D, E):
    pass
class G(F, D):
    pass
class H:
    pass
class Foo(H, G):
    pass

类的: Foo-> H -> G -> F -> E -> D -> B -> A -> C.

新式类的多继承

mro序列

MRO是一个有序列表L,在类被创建时就计算出来

通用计算公式为:

mro(Chird(Base1,Base2)) = [child] + merge(mro(Base1),mro(Base2),[Base1,Base2])
# 其中child继承自Base1,Base2

如果继承一个基类:class B(A)

这时候B的mro序列为

mro(B) = mro(B(A))
= [B] + merge(mro(A) + [A])
= [B] + merge([A] + [A])
= [B,A]

如果继承至多个基类:class B(A1,A2,A3)

mro(B) = mro( B(A1, A2, A3 …) )
= [B] + merge( mro(A1), mro(A2), mro(A3) ..., [A1, A2, A3] )
= ...

计算结果为列表,列表中至少有一个元素即类自己,如上述示例[A1,A2,A3],merge操作是C3算法的核心

表头和表尾

表头:
  列表的第一个元素

表尾:
  列表中表头以外的元素集合(可以为空)

示例
  列表:[A, B, C]
  表头是A,表尾是B和C

列表之间的+操作

+操作:

[A] + [B] = [A, B]

(以下的计算中默认省略)

如计算merge( [E,O], [C,E,F,O], [C] )
有三个列表 :  ①      ②          ③
merge不为空,取出第一个列表列表①的表头E,进行判断                              
   各个列表的表尾分别是[O], [E,F,O],E在这些表尾的集合中,因而跳过当前当前列表
取出列表②的表头C,进行判断
   C不在各个列表的集合中,因而将C拿出到merge外,并从所有表头删除
   merge( [E,O], [C,E,F,O], [C]) = [C] + merge( [E,O], [E,F,O] )
进行下一次新的merge操作 ......
---------------------

计算mro(A)方式:

mro(A) = mro( A(B,C) )

原式= [A] + merge( mro(B),mro(C),[B,C] )

  mro(B) = mro( B(D,E) )
         = [B] + merge( mro(D), mro(E), [D,E] )  # 多继承
         = [B] + merge( [D,O] , [E,O] , [D,E] )  # 单继承mro(D(O))=[D,O]
         = [B,D] + merge( [O] , [E,O]  ,  [E] )  # 拿出并删除D
         = [B,D,E] + merge([O] ,  [O])
         = [B,D,E,O]

  mro(C) = mro( C(E,F) )
         = [C] + merge( mro(E), mro(F), [E,F] )
         = [C] + merge( [E,O] , [F,O] , [E,F] )
         = [C,E] + merge( [O] , [F,O]  ,  [F] )  # 跳过O,拿出并删除
         = [C,E,F] + merge([O] ,  [O])
         = [C,E,F,O]

原式= [A] + merge( [B,D,E,O], [C,E,F,O], [B,C])
    = [A,B] + merge( [D,E,O], [C,E,F,O],   [C])
    = [A,B,D] + merge( [E,O], [C,E,F,O],   [C])  # 跳过E
    = [A,B,D,C] + merge([E,O],  [E,F,O])
    = [A,B,D,C,E] + merge([O],    [F,O])  # 跳过O
    = [A,B,D,C,E,F] + merge([O],    [O])
    = [A,B,D,C,E,F,O]
---------------------
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!