27类和对象---继承与派生

1、继承:新建的类(称为子类)可以继承一个或多个父类(称为父类或超类),子类会继承父类的属性,从而解决代码重用问题。

  Object类是所有python的基类,它提供了一些常用的方法(如__str__)的实现。

  继承的功能:  1、通过继承实现代码重用     

          2、通过接口实现归一化设计

python3中都是新式类
python2中继承了object的是新式类,新式类与经典类的区别在继承顺序的区别、类实例类型的区别 

class ParentClass1: #定义父类
    pass

class ParentClass2: #定义父类
    pass

class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
    pass

class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类,从左至右
    pass


# 查看继承
print(SubClass1.__base__) #只查看从左到右继承的第一个类
print(SubClass2.__bases__)#所有继承的父类,(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)

 2、使用继承来重用代码

派生:子类也可以添加自己新的属性或者在自己这里重新定义这些属性

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

class Bar(Foo):
    def f1(self): #派生,定义自己的属性
        print('Bar.f1。。。')

b=Bar()
b.f2() # 继承,类的属性查找其实和函数的差不多,找f1()的时候还是先在bar()的作用域里

 

3、组合和继承

(1)继承的方式
通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物。
当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如老师是人,学生是人
(2)组合的方式
用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,
教授教python和linux课程,教授有学生s1、s2、s3...
当类之间有显著不同,并且较小的类是较大的类的组成部分时,用组合较好

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

class Course:
    def __init__(self, name, period, price):
        self.name = name
        self.period = period
        self.price = price
    def tell_info(self):
        print('{}:{}:{}'.format(self.name, self.period, self.price))

class Teacher(People):
    def __init__(self, name, age, sex, job_title):
        People.__init__(self, name, age, sex)
        self.job_title = job_title
        self.course = []
        self.students = []

class Student(People):
    def __init__(self, name, age, sex):
        People.__init__(self, name, age, sex)
        self.course = []

egon = Teacher('egon',19,'male','0001')
min = Teacher('min',33,'female','0002')

python = Course('python','3mons',30000)
java = Course('java', '4mons',40000)

s1 = Student('cc',19,'male')
s2 = Student('cc2',19,'male')
s3 = Student('cc3',19,'male')
s4 = Student('cc4',19,'male')

egon.course.append(python)
egon.course.append(java)
min.students.append(s1)
min.students.append(s2)
s1.course.append(python)

for c in egon.course:
    c.tell_info()

 

4、接口与归一化设计
基于一个接口实现类,那么所有这些类产生的对象在使用时,从用法上来说都是一样的
归一化让使用者无需关心对象的类是什么,只需要知道这些对象具备哪些功能就可以了

# 模仿interface
class Interface:#定义接口Interface类来模仿接口的概念,python中压根就没有interface关键字来定义一个接口。
    def read(self): #定接口函数read
        pass

    def write(self): #定义接口函数write
        pass


class Txt(Interface): #文本,具体实现read和write
    def read(self):
        print('文本数据的读取方法')

    def write(self):
        print('文本数据的读取方法')

class Sata(Interface): #磁盘,具体实现read和write
    def read(self):
        print('硬盘数据的读取方法')

    def write(self):
        print('硬盘数据的读取方法')

class Process(Interface):
    def read(self):
        print('进程数据的读取方法')

    def write(self):
        print('进程数据的读取方法')

# 只是像,但子类可以不用实现,这就用到了抽象类

 

5、抽象类
借助模块的实现,只能被继承, 不能被实例化,而且子类必须实现抽象方法

抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),
而接口只强调函数属性的相似性。

import abc  #利用abc模块实现抽象类
class All_file(metaclass=abc.ABCMeta):
    all_type = 'file'
    @abc.abstractclassmethod  #定义抽象方法,不用实现
    def read(self):
        pass

    @abc.abstractclassmethod
    def write(self):
        pass

# 子类继承,必须定义父类的两个方法,否则报错
class Txt(All_file):
    def read(self):
        print('Txt read....')
    def write(self):
        print('Txt write....')

6、继承顺序:新式类:广度优先
经典类:深度优先
可以通过类.__mro__查看
三条准则:1、子类会先于父类检查
2、多个父类会根据它们在列表中顺序检查
3、如果对下一个类存在两个合法的选择,那么选择第一个父类


7、子类中调用父类的方法

方法一:指名道姓,即父类名.父类方法()

class Vehicle:  # 定义交通工具类
    Country = 'China'

    def __init__(self, name, speed, load, power):
        self.name = name
        self.speed = speed
        self.load = load
        self.power = power

    def run(self):
        print('开动啦...')


class Subway(Vehicle):  # 地铁
    def __init__(self, name, speed, load, power, line):
        Vehicle.__init__(self, name, speed, load, power)
        self.line = line

    def run(self):
        print('地铁%s号线欢迎您' % self.line)
        Vehicle.run(self)#在子类中调用父类方法,直接用父类.方法()

line1 = Subway('df',1000,'1000人','','1号线')
line1.run()

 

方法二:super().父类方法()

class Vehicle:
    Country = 'China'
    def __init__(self, name, speed, load, power):
        self.name = name
        self.speed = speed
        self.load = load
        self.power = power

    def run(self):
        print('开动了。。。。')

class Subway(Vehicle):
    def __init__(self, name, speed, load, power, line):
        super().__init__(name, speed, load, power)
        self.line = line

    def run(self):
        print('{}欢迎你'.format(self.line))
        # 在py3中,super()====>super(Subway,self)
        super().run()

line1 = Subway('df',1000,'1000人','','1号线')
line1.run()

 

posted @ 2021-04-05 14:47  cheng4632  阅读(125)  评论(0编辑  收藏  举报