Python课程回顾(day22)

类和对象之继承 

1.什么是继承?

  继承在我们人类现实世界中可以形容为一种遗传,就像孩子与爸爸之间的关系,爸爸可以将所有事物传给孩子的意思..

  而在我们的python中之前也提到过一种继承,是在logging模块里说过的,它跟我们的现实世界恰好相反,是父类继承子类的一种继承

  今天我们所说的这种继承是类和对象中的继承,在程序中继承是一种新建子类的方式,新创建的类被称之为子类/派生类,被继承的类称之为父类/基类/超类,而新创建的子类则可以重用到父类的属性

 

2.为何要用继承?

  假设我们的父类有多个子类,而多个子类都要用到相同一段功能,这时候就可以将这段功能放置父类内,不仅子类也可以使用代码,还减少了代码冗余的现象

 

3.如何使用继承?

如下:在继承类的括号内加上被继承类的类名即完成继承,而在python中又分为单继承与多继承的特点

class Parent1:
    pass

class Parent2
    pass

class Sub1(Parent1):          # 继承Parent1
    pass

class Sub2(Parent1, Parent2): # 继承Parent1与Parent2
    pass

print(Sub1.__bases__)
print(Sub2.__bases__) # 使用__bases__查看当前的被继承类(父类)

 

python2与python3继承关系的区别

  python2与python3在继承上最大的区别就在于是否继承了object,object也是一个类,是python内部封装好的一些个功能,而在python2中有时是用不到继承object的,但在python3中,默认会直接继承object.总的来说,继承的类型分为两大类:

  新式类:但凡继承了object类的子类以及子子类...,都称之为新式类.

  经典类:但凡没有继承object类的子类以及子子类...,都称之为经典类

 

继承的应用1:

class Oldboy:
    school = 'oldboy'
    pass

class Students(Oldboy):
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

    def choose_class(self):
        print('%s is choosing class' % self.name)

class Teacher(Oldboy):
    def __init__(self, name, age, gender, level, salary):
        self.name = name
        self.age = age
        self.gender = gender
        self.level = level
        self.salary = salary
    def score(self, stu, num):
        stu.num = num
        print('%s老师给%s同学打了%s分' % (self.name, stu.name, num))

stu = Students('孔令飞', 23, 'male')
teac = Teacher('egon', 26, 'male', 10, 10000)
print(stu.school)      # 继承之后可以查找父类的属性
print(teac.school)     # 继承之后可以查找父类的属性

继承的应用2:

在子类派生出的新功能中如何重用父类的功能:

方式一:指名道姓的访问某一类中的函数,与继承无关

class Oldboy:
    school = 'oldboy'

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


class Students(Oldboy):
    def choose_class(self):
        print('%s is choosing class' % self.name)


class Teacher(Oldboy):                            
    def __init__(self, name, age, gender, level, salary):
        Oldboy.__init__(self, name, age, gender)  # 直接调用父类的init,减少重复代码,产生对象(直接使用Oldboy内的init函数,与继承无关)
        self.level = level                        # 为其对象添加新的属性
        self.salary = salary

    def score(self, stu, num):
        stu.num = num
        print('%s老师给%s同学打了%s分' % (self.name, stu.name, num))


stu = Students('孔令飞', 23, 'male')     # 此时调Students等同于调Students内的init函数,但Students内没有就去父类Oldboy找
# print(stu.__dict__)                   # 证明子类确实重用父类的init函数
teac = Teacher('egon', 26, 'male', 10, 10000)

stu.choose_class()
teac.score(stu,100)

属性查找(方式2的前提):

# 在单继承背景下,无论是经典类还是新式类属性查找顺序都是一样的

# 例:


class Foo:
    def f1(self):
        print('Foo.f1')

    def f2(self):
        print('Foo.f2')          # 2.打印一
        self.f1()                # 3.打印成功之后又调用自身的f1,若自身内有则打印


class Bar(Foo):
    def f1(self):
        print('Bar.f1')          # 4.打印二


obj = Bar()
obj.f2()                         # 1.首先当前对象内没有f2,然后去类找,类也没有,则去父类
# 在多继承背景下,如果一个子类继承了多个分支,
# 但是多个分支没有汇聚到一个非object类
# (汇聚到一点则称之为菱形继承----->(从最低点向上分支又进行汇聚))
# 无论新式类还是经典类属性查找顺序都是一样的
# 它会按照从左到右的分支一个一个查找下去

class E:
    xxx = 'E'


class F:
    xxx = 'F'


class D:
    xxx = 'D'


class C(F):
    xxx = 'C'


class B(E):
    xxx = 'B'


class A(B, C, D):  # 从左到右一个分支一个分支的去找,若分支内也存在继承关系,则会查找完毕后再进入下一个分支查找
    xxx = 'A'


obj = A()
obj.xxx = 1
print(obj.xxx)
# 查找顺序为:obj内-->A-->B-->E-->C-->F-->D-->object
# 在多继承背景下,如果一个子类继承了多个分支,
# 而且多个分支汇聚到了一个非object类

# 新式类:广度优先查找 # 经典类:深处优先查找 class G: pass class E(G): xxx = 'E' class F(G): xxx = 'F' class D(G): xxx = 'D' class C(F): xxx = 'C' class B(E): xxx = 'B' class A(B, C, D): xxx = 'A' obj = A() obj.xxx = 1 print(obj.xxx) # 深度优先查找顺序为:当前对象内-->类-->A-->B-->E-->G-->C-->F-->D # 广度优先查找顺序为:当前对象内-->类-->A-->B-->E-->C-->F-->D-->G-->object

print(A.mro()) # 根据c3线性化算法算出来的一种属性查找方法,结果是一个列表,会按照列表内的顺序依次进行查找,只要在类定义完成时c3算法会自动算出属性的查找方法
           c3算法无论是否为菱形继承都会算出属性查找方法

继承的应用2:

方式二:super方法

在python3中,super是可以不用传入参数的,调用该函数会得到一个特殊的对象,该对象是专门用来访问父类中的属性的

super会严格按照当前类的mro列表依次进行属性查找

class Oldboy:
    school = 'oldboy'

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


class Students(Oldboy):
    def choose_class(self):
        print('%s is choosing class' % self.name)


class Teacher(Oldboy):                            
    def __init__(self, name, age, gender, level, salary):
        super(Teacher,self).__init__(name,age,gender)     # super方法得到的对象就是专门查找父类属性的,所有直接调用父类的__init__函数来为teac添加属性
        self.level = level                       
        self.salary = salary

    def score(self, stu, num):
        stu.num = num
        print('%s老师给%s同学打了%s分' % (self.name, stu.name, num))


stu = Students('孔令飞', 23, 'male')   
# print(stu.__dict__)                   
teac = Teacher('egon', 26, 'male', 10, 10000)

stu.choose_class()
teac.score(stu,100)

 

posted @ 2018-10-23 19:43  BlackLinks  阅读(219)  评论(0编辑  收藏  举报