类的“继承”、“派生”

一、继承

1、什么是继承

  继承是一种新建类的方式,新建的类称之为子类或派生类,继承的父类称之为基类或超类。

    1)在python中,一个子类可以继承多个父类

    2)在其他语言中,一个子类只能继承一个父类

 

2、继承的作用

  减少代码的冗余

 

3、如何实现类的继承

  1)先确认谁是子类,谁是父类

  2)在定义子类时      子类名(父类名)

# 父类1
class Father1:
    x = 1

# 父类2
class Father2:
    y = 2

# 父类3
class Father3:
    z = 3

# 子类
class Sub(Father1, Father2, Father3):
    pass

# 查看父类:子类.__bases__
print(Sub.__bases__)
# 继承父类的属性
print(Sub.x, Sub.y, Sub.z)

  执行结果:

(<class '__main__.Father1'>, <class '__main__.Father2'>, <class '__main__.Father3'>)
1 2 3

 

4、寻找继承关系

  1)确认谁是子类

  2)确认谁是父类

    - 得先抽象,再继承

      - 抽取对象之间相似的部分,总结出类

      - 抽取类之间相似的部分,总结出父类

 

  # 例,写一个老师类和学生类:

# 老师类
class JldTeacher:
    school = "Jld"
    country = "China"

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

    # 老师修改分数
    def chang_score(self):
        print(f"{self.name}老师正在修改分数。。。")


# 学生类
class JldStudent:
    school = "Jld"
    country = "China"

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

    # 学生选择课程
    def chose_course(self):
        print(f"{self.name}学生正在选择课程。。。")

  注意:老师类和学生类有相似的部分,造成代码冗余

 

  # 解决代码冗余问题:使用继承

# 学校类[是家里蹲(Jld)学校老师(JldTeacher)和学生(JldStudent)的父类)]
class Jld:
    school = "Jld"
    country = "China"

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


# 老师类[是家里蹲学校(Jld)的子类]
class JldTeacher(Jld):

    # 老师修改分数
    def chang_score(self):
        print(f"{self.name}老师正在修改分数。。。")


# 学生类[是家里蹲学校(Jld)的子类]
class JldStudent(Jld):

    # 学生选择课程
    def chose_course(self):
        print(f"{self.name}学生正在选择课程。。。")



student_obj = JldStudent("张三儿", 85, "female")
# 查看student_obj的名称空间
print(student_obj.__dict__)
print(student_obj.name, student_obj.age, student_obj.sex)
teacher_obj
= JldStudent("王五", 101, "male") # 查看teacher_obj的名称空间 print(teacher_obj.__dict__)
print(teacher_obj.name, teacher_obj.age, teacher_obj.sex)

  执行结果:

{'name': '张三儿', 'age': 85, 'sex': 'female'}
张三儿 85 female
{'name': '王五', 'age': 101, 'sex': 'male'}
王麻子 101 male

 

5、在继承背景下对象查找属性的顺序

  在继承背景下对象查找属性的顺序:

    1)先从对象自己的名称空间找

    2)对象中没有,从子类的名称空间找

    3)子类中没有,从父类的名称空间找,若父类没有,则会报错

 

  注意:程序的执行顺序是由下到上。父类必须定义在子类的上方

# 父类
class Goo:
    x = 10
# 子类
class Foo(Goo):
    # x = 100
    pass

foo_obj = Foo()
# foo_obj.x = 1000
print(foo_obj.x)

  执行结果:

10

 

 

二、派生

1、什么是派生

  派生:

    指的是子类继承父类的属性和方法,并且派生出自己独有的属性与方法。

    若子类中的方法名与父类中的方法名相同(重写),就先用子类的

# 父类
class Foo():
    def f1(self):
        print("from Foo.f1..")

    def f2(self):
        print("from Foo.f2..")
        self.f1()

# 子类
class Goo(Foo):
    # 子类中存在有与父类一样的方法叫做重写
    def f1(self):
        print("from Goo.f1..")

    def func(self):
        print("from Goo.func..")

goo_obj = Goo()
print(goo_obj.f1())    # from Goo.f1..
print(goo_obj.func())    # from Goo.func..
# 派生后继承对象验证:
print(goo_obj.f2())    # from Foo.f2..    from Goo.f1..

  执行结果:

from Goo.f1..
from Goo.func..
from Foo.f2..
from Goo.f1..

 

2、子类派生

  子类派生:子类继承父类,重用父类的属性与方法,并且派生出自己的属性与方法。

  有两种方式:

    1)直接引用父类的__init__为其传参,并添加子类的属性

    2)通过super来指向父类的属性

      super是一个特殊的类,调用super得到一个对象,该对象指向父类的名称空间

 

  注意:使用哪一种都可以,但不能两种混合使用

 

  # 写一个老师类和学生类

  # 需求:为老师添加薪资属性,为学生添加年级属性

  # 第一种方式:直接引用父类的__init__为其传参,并添加子类的属性

# 第一种方式:直接引用父类的__init__为其传参,并添加子类的属性
class Jld:
    school = "Jld"
    # country = "China"
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex


class JldTeacher(Jld):
    def __init__(self, name, age, sex, sal):
        # 引用父类Jld的属性
        Jld.__init__(self, name, age, sex)
        # 派生(添加)出子类JldTeacher自己的属性
        self.sal = sal

    # 老师修改分数
    def chang_score(self):
        print(f"{self.name}老师正在修改分数。。。")


class JldStudent(Jld):
    def __init__(self, name, age, sex, grade):
        # 引用父类Jld的属性
        Jld.__init__(self, name, age, sex)
        # 派生(添加)出子类JldStudent自己的属性
        self.grade = grade

    # 学生选择课程
    def chose_course(self):
        print(f"{self.name}学生正在选择课程。。。")



teacher_obj = JldTeacher("王五", 89, "female", 1000000)
student_obj = JldStudent("张三儿", 87, "male", "大二")
print(teacher_obj.name, teacher_obj.sex, teacher_obj.age, teacher_obj.sal)
print(student_obj.name, student_obj.sex, student_obj.age, student_obj.grade)

  执行结果:

王五 female 89 1000000
张三儿 male 87 大二

 

  # 第二种方式:通过super来指向父类的属性

# 第二种方式:通过super来指向父类的属性
class Jld:
    school = "Jld"
    # country = "China"
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex


class JldTeacher(Jld):
    def __init__(self, name, age, sex, sal):
        # super()  --> 特殊的对象 --> 对象.属性 --> 父类的名称空间
        # 会将外部调用的类当做第一个参数自动传给__init__
        super().__init__(name, age, sex)
        # 派生(添加)出子类JldTeacher自己的属性
        self.sal = sal

    # 老师修改分数
    def chang_score(self):
        print(f"{self.name}老师正在修改分数。。。")


class JldStudent(Jld):
    def __init__(self, name, age, sex, grade):
        # 会将外部调用的类当做第一个参数自动传给__init__
        super().__init__(name, age, sex)
        # 派生(添加)出子类JldStudent自己的属性
        self.grade = grade

    # 学生选择课程
    def chose_course(self):
        print(f"{self.name}学生正在选择课程。。。")



teacher_obj = JldTeacher("王五", 89, "female", 1000000)
student_obj = JldStudent("张三儿", 87, "male", "大二")
print(teacher_obj.name, teacher_obj.sex, teacher_obj.age, teacher_obj.sal)
print(student_obj.name, student_obj.sex, student_obj.age, student_obj.grade)

  执行结果:

王五 female 89 1000000
张三儿 male 87 大二
posted @ 2020-10-24 22:50  chchcharlie、  阅读(770)  评论(0编辑  收藏  举报