面向对象之继承

一.继承基础

1.什么是继承?

继承指的是一种关系,它必须存在两个对象,才会发生继承这件事。在程序中,继承指的是类与类之间的关系。被继承的称为父,继承的称为子。

2.为什么要使用继承?

在程序中,通过继承可以直接使用父类已有的代码,从而简化代码。

3.如何使用继承?

语法:在子类中,类名后面加括号,括号里写上父类的名称即可,可以是多个,用逗号分隔开。

子类可以使用父类中的属性,也可以使用父类中的函数。

# class Father:
#     pass
#
#
# class GanDie:
#     pass
#
# # 在子类中 类名后面加上括号,些上父类的名称即可,
# # 在python中一个子类可以有多个父类,多个父类在括号中用逗号隔开,,这一点在其他语言中是不支持的
# class Son(Father,GanDie):
#     pass



class Parent:
    year = 2018

    def coding(self):
        print("正在编程........")



class Sub(Parent):
    pass

print(Parent.year)

print(Sub.year)

# Sub.coding()


s = Sub()
print(s.year) # 子类可以使用父类中的属性
s.coding() # 子类也可以父类中的函数
继承的使用

子类继承父类之后会出现一个问题,就是子类可能会继承到一些不应该有的属性,这就需要用到抽象的概念。

抽象指的是抽取多个类中相同的部分形成另一个类。这样就可以避免继承到一些不应该有的内容,在抽取的过程中,也可能会产生一些跟业务需求无关的类,但是并不影响。

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

    def eat(self):
        print("正在吃饭....")

    def study(self):
        print("正在学习....")

class Teacher(Person):

    def teaching(self):
        print("老师正在上课......")

t1 = Teacher("blex" ,30 ,"woman")
t1.eat()
t1.study()


class Student(Person):
    pass

stu1 = Student("张三" ,20 ,"man")
stu1.eat()
stu1.study()
抽象

二.派生与覆盖

1.什么是派生?

派生指的是子类继承某个父类,并且子类拥有自己独特的属性或者技能。只要子类中出现了任何新的内容,它就是一个派生类。

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

    def sayHI(self):
        print("hello 我是%s 今年%s岁 性别:%s" % (self.name,self.age,self.sex))


# Test不能称为派生类 , 因为没与任何独特的内容与父类完全一致
class Test(Person):
    pass

# 派生类属于子类吗?   派生类一定是某个子类
# Student类就成为 Person类的派生类


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

    # 上课
    def up_class(self):
        print("%s 正在上课.....")
派生

2.什么是覆盖?

在子类中,如果存在与父类相同的属性名称时,优先使用子类中的属性,这种行为称之为覆盖。

三.子类访问父类的方法

简单的来说有两种方法:

1.指名道姓的访问(父类名点语法)

2.用super()函数访问(super()点语法)。该函数一定是用在存在继承关系的子类中的。在python2中用法:super(子类名,self)点语法。

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

    def sayHI(self):
        print("hello 我是%s 今年%s岁 性别:%s" % (self.name,self.age,self.sex))


class Student(Person):
    def __init__(self,name,age,sex,number):
        # self.name = name
        # self.age = age
        # self.sex = sex
        #上述代码与父类中完全相同
        Person.__init__(self,name,age,sex)
        self.number = number
    # 上课
    def up_class(self):
        print("%s 正在上课.....")

    def sayHI(self):
        # print("hello 我是%s 今年%s岁 性别:%s" % (self.name,self.age,self.sex))
        # 访问父类中的方法来简化代码
        # 指名道姓
        Person.sayHI(self)
        
        print("学号:",self.number)

stu1 = Student("阿三",20,"woman","9527")
# print(stu1)
# print(stu1.name,stu1.age,stu1.sex)
stu1.sayHI()
方法一
class Person:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
        print(self)

    def sayHI(self):
        print("hello 我是%s 今年%s岁 性别:%s" % (self.name,self.age,self.sex))

class Student(Person):
    def __init__(self,name,age,sex,number):
        # self.name = name
        # self.age = age
        # self.sex = sex
        # 子类中重用父类种方法的方式2
        # super() # 表示创建一个特殊的对象 用于调用父类的方法
        # super().__init__(name,age,sex)
        # 了解:在python2中 super的使用方式有所不同 需要传入当前类,当前对象
        super(Student,self).__init__(name,age,sex)
        self.number = number

    # 上课
    def up_class(self):
        print("%s 正在上课.....")

stu1 = Student("阿三",20,"woman","9527")
print(stu1)
print(stu1.name,stu1.age,stu1.sex)
方法二

四.继承的属性查找顺序

查找顺序:对象---》类---》父类---》父类的父类......

优先查找对象,如果不存在,则找类,如果类中不存在,则会沿着继承关系一直找到最顶层的父类。方法的查找顺序也是一样。

class S:
    age = 17

    def f1(self):
        print("S f1")

class A(S):
    # age = 18
    # def f1(self):
    #     print("A f1")
    pass
class B(A):
    # age = 19
    # def f1(self):
    #     print("B f1")
    pass
b = B()
# b.age = 20

print(b.age)

print(b.__dict__)
print(B.__dict__)
print(A.__dict__)

# 对象 -> 类 ->父类 ->父类的父类.....
# 优先找对象 如歌对象没有 则找类,如果类没有,会沿着继承关系一直找到最顶层的父类
# 无论是属性还是方法 查找顺序是一样的
b2 = B()
b2.f1()
基本查找顺序

如果继承关系为菱形结构,那么属性的查找方式有两种,分别是:深度优先和广度优先

# class E:
#     a = 5
#
# class A(E):
#     a = 4
#     pass
#
# class B:
#     a = 3
#     pass
#
# class C:
#     a = 2
#     pass
#
# class D(A,B,C):
#     # a = 1
#     pass
#
# d1 = D()
# # d1.a = 10
# print(d1.a)

# 1.按照继承的顺序 先继承谁就先找谁


class S:
    a = 100

class A(S):
    # a = 1
    pass
class B(S):
    # a = 2
    pass
class C(S):
    # a = 3
    pass
class D(A):
    # a = 4
    pass
class E(B):
    # a = 5
    pass
class F(C):
    # a = 6
    pass
class G(D,E,F):
    pass


g1 = G()
print(g1.a)
print(G.mro())

"""
s
a,b,c
d,e,f
g
"""
菱形继承的属性查找

五.经典类与新式类

新式类:所有直接或间接继承object的类都是新式类。object称之为根类,即所有的类都源自于object类。(创建对象时,需要申请内存空间,创建新的名称空间,将对象的属性放入名称空间,这一些了复杂的基础操作,都有object来完成。简单地说:object提供了一些常用的基础操作。)

在python3中默认所有类都是新式类,在python2中默认是经典类(不会自动继承object)。

__bases__用于查看父类,mro()方法是一个列表,存放的是属性的查找顺序,这个mro()是通过c3线性算法得来。

"super访问父类内容时 按照mro列表属性查找"

class S:
    def f1(self):
        print("s f1")

class A(S):
    pass

class B(S):
    def f1(self):
        print("b f1")
    pass

class C(A,B):
    def f2(self):
        print("c f2")
        super().f1()


print(C.mro())
c1 = C()
c1.f2()

class S:
    pass
class Student(S):
    pass

# __bases__用于查看父类
print(Student.__bases__)

# 显示属性的查找顺序列表,属性查找属性就是按照该列表来查找的
print(Student.mro())
View Code
posted @ 2018-12-14 15:23  起个名字、真难啊  阅读(217)  评论(0编辑  收藏  举报