继承:单继承与多继承/新式类的广度优先查询/经典类的深度优先查询

本节主要内容:

1.继承

2.新式类与经典类

3.多继承的优先查询

一.继承

定义一个类,class Dog(Animal)  其中括号里面的Animal是父类/基类/超类,括号外面的Dog是子类/派生类.

继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类.

当我们在定义多个类的时候,发现要用到相同的方法或变量,如果每个类都要写相同的方法和变量,那么代码就会重复,为了减少代码,可以用继承来解决.

# encoding:utf-8
# 如果是用的python2,python2默认使用ascii码,先再第一行写上encoding:utf-8 ;
# python3默认使用的是utf-8

组合:让一个类对象与另一个类的对象发生关系
继承:让类与类发生关系

面向对象的三大特性: 继承 多态 封装
面向对象为什么要有继承?继承的好处是什么?
a, 提高了代码的复用性
b:提高了代码的维护性
c:让类与类之间产生了关系,是多态的前提
# 子类以及子类实例化的对象 可以访问父类的任何方法或变量.
# 类名可以访问父类所有内容
# 子类实例化的对象也可以访问父类所有内容
# 父类不能访问子类的东西

#这几个类用到了相同的方法和变量,为了提高代码的复用性,引入继承的思想
class Animal:
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age

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

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

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

class Animal:
    breath = '呼吸'

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

    def eat(self):
        print(self)
        print('动物都需要进食....')


class Person(Animal):  # 括号里面的 父类,基类,超类   括号外面的 子类,派生类.
    pass


class Cat:
    pass


class Dog:
    pass


p1 = Person('alex', 'laddyboy', 1000)
print(p1.__dict__)  #{'name': 'alex', 'sex': 'laddyboy', 'age': 1000}

# 初识继承:
# 子类以及子类实例化的对象 可以访问父类的任何方法或变量.
# 类名可以访问父类所有内容
print(Person.breath)   #呼吸
Person.eat(111)   #111
                  #动物都需要进食....
# 子类实例化的对象也可以访问父类所有内容
print(p1.breath)  #呼吸
print(p1)     #<__main__.Person object at 0x0000006ECD9A7C88>
p1.eat()    #<__main__.Person object at 0x0000006ECD9A7C88>
            #动物都需要进食....

查询顺序:子类的对象空间==>子类空间==>父类空间

只执行父类的方法:子类中不要定义与父类同名的方法
只执行子类的方法:在子类创建这个方法.

既要执行子类的方法,又要执行父类的方法?
有两种解决方法.
1,Animal.__init__(self, 参数)
2,super().__init__(参数)
class Animal:
    def __init__(self,name):
        self.name=name

    # def eat(self):
    #     print("会")

    def eat(self):
        print("%s会吃" %self.name)

    def drink(self):
        print("%s会喝" %self.name)

class Cat(Animal):
    def tian_zhua_zi(self):
        print("%s会舔爪子" %self.name)

class Dog(Animal):
    def kan_jia(self):
        print("%s会看家" %self.name)

class Chicken(Animal):
    def xia_dan(self):
        print("%s会下蛋" %self.name)


class Bird(Animal):
    def __init__(self,name,wing):     #self=Bird的实例化对象b,  name="鹦鹉",  wing="绿翅膀"
        #Animal.__init__(self,name)    #类名.函数+(),,相当于函数的调用,()里面装的是实参,把self,name当做实参传进来
                     # (self现在是指Bird的对象b,也就是个空间地址),然后执行函数,父类的函数对name进行封装,函数执行完毕,
                     # 执行下一步,self.wing=wing,是Bird自身对对象的属性进行封装.
        super().__init__(name)#super(Bird,self).__init__(name)  用super()直接把想要的父类的参数拿过来,然后封装自己的参数
        self.wing=wing
        print(name,wing)

    def eat(self):
        super().eat()
        print("%s会吃小虫子" % self.name)


# c=Cat()     #父类中没有__init__方法,实例化一个子类的对象,子类的对象调用父类的方法,也会执行父类方法中的内容
# c.eat()

# c=Cat("猫")
# c.eat()
# c.drink()
# c.tian_zhua_zi()
#
# d=Dog("狗")
# d.eat()
# d.drink()
# d.kan_jia()
#
# j=Chicken("鸡")
# j.eat()
# j.drink()
# j.xia_dan()

二.新式类与经典类


继承: 单继承,多继承.

  单继承:只继承一个父类
   class A(B):
  pass
多继承:继承两个及两个以上的父类
   class A(B,C):
   pass
  
: 经典类, 新式类

新式类: 凡是继承object类都是新式类.
   python3x 所有的类都是新式类,因为python3x中的类都默认继承object.

经典类: 不继承object类都是经典类
   python2x:(既有新式类,又有经典类) 所有的类默认都不继承object类,所有的类默认都是经典类.你可以让其继承object.


三.多继承的优先查询

1.单继承: 新式类,经典类查询顺序一样.
2.多继承:
新式类: 遵循广度优先.
经典类: 遵循深度优先.

3.多继承的新式类
  
广度优先
: 一条路走到倒数第二级,判断,如果其他路能走到终点,则返回走另一条路.如果不能,则走到终点.

4.多继承的经典类  

深度优先 : 一条路走到底.

5.查询类的继承顺序: 类名.mro()

class A:
    def func(self):
        print('IN A')

class B(A):
    pass
    # def func(self):
    #     print('IN B')

class C(A):
    pass
    # def func(self):
    #     print('IN C')

class D(B):
    pass
    # def func(self):
    #     print('IN D')

class E(C):
    pass
    # def func(self):
    #     print('IN E')

class F(D,E):
    pass
    # def func(self):
    #     print('IN F')

f1 = F()
print(F.mro())
#[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
6.多继承广度优先查询算法
#例子1

class
H: pass class G(H): pass class F(H): pass class E(G): pass class D(F): pass class C(E): pass class B(D): pass class A(B, C, D): pass print(A.mro()) ''' 首先找到A继承的三个类的深度继承顺序,放到一个列表中 B [B,D,F,H] C [C,E,G,H] D [D,F,H] 每个列表的第一个元素为头部,其它位置元素都为尾部,从第一个列表的头部开始找,找其他列表中尾部是否含有 这个类名,如果没有,提取出来放到一个列表中,如果有,找下一个列表的头部,循环下去 只要提取来一个,我们就从第一个列表的头部接着重复上面的操作. A [A] [B,D,F,H] [C,E,G,H] [D,F,H] [B,C,D] A #找到第一个列表的头A,其他列表尾部没有A,把A取出来,如果其他列表的头部有A则剔除 [] [B,D,F,H] [C,E,G,H] [D,F,H] [B,C,D] B [] [D,F,H] [C,E,G,H] [D,F,H] [C,D] C [] [D,F,H] [E,G,H] [D,F,H] [D] D [] [F,H] [E,G,H] [F,H] [] F [] [H] [E,G,H] [H] [] E #找到第一个列表的头部H,但是其他列表尾部有H,所以跳过这个列表,去下一个列表取头部 [] [H] [G,H] [H] [] G [] [H] [H] [H] [] H [] [] [] [] [] lst = [A,B,C,D,F,E,G,H] '''
#例子2

class
F: pass class E: pass class D: pass class C(D, F): pass class B(E, D): pass class A(B, C): pass print(A.mro()) ''' 首先找到A继承的两个类的深度继承顺序 把B作为子类,找出B类的查询顺序 B [B] [E] [D] [E,D] B [] [E] [D] [E,D] E [] [] [D] [D] D [] [] [] []
lst = [B,E,D] 把C作为子类,找出C类的查询顺序 C [C] [D] [F] [D,F] C [] [D] [F] [D,F] D [] [] [F] [F] F [] [] [] [] lst = [C,D,F] A [A] [B,E,D] [C,D,F] [B,C] A [] [B,E,D] [C,D,F] [B,C] B [] [E,D] [C,D,F] [C] E [] [D] [C,D,F] [C] C [] [D] [D,F] [] D [] [] [F] [] F [] [] [] [] lSt = [A,B,E,C,D,F]
'''
 
原文地址:https://www.cnblogs.com/mwj-blog1/p/9389535.html