Python进阶之派生和组合

【一】派生

【1】什么是派生

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

【2】派生的属性与方法

  • 子类可以派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找
class School(object):
    school = '北京大学'

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


class Student(School):
    # 派生 : 派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

    def read(self):
        print(f"{self.age}岁的{self.sex}学生{self.name}的学校是{self.school}")


# 只会找自己类中的__init__,并不会自动调用父类的
obj = Student('ligo', 18, '男')
print(obj.name, obj.sex, obj.age)
# ligo 男 18
obj.read()
# 18岁的男学生ligo的学校是北京大学

(1)继承方式一:指名道姓的调用某一个类的函数

class School(object):
    school = '北京大学'

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


class Student(School):
    # 派生 : 派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找
    def __init__(self, name, age, sex):
        # 直接调用 父类 中 的 __init__ 方法
        # 调用的是函数,因而需要传入self
        School.__init__(self, name, age)
        self.sex = sex

    def read(self):
        print(f"{self.age}岁的{self.sex}学生{self.name}的学校是{self.school}")


# 只会找自己类中的__init__,并不会自动调用父类的
obj = Student('ligo', 18, '男')
print(obj.name, obj.sex, obj.age)
# ligo 男 18
obj.read()
# 18岁的男学生ligo的学校是北京大学

(2)继承方式二:超类(super())

  • 调用super()会得到一个特殊的对象
  • 该对象专门用来引用父类的属性
  • 且严格按照MRO规定的顺序向后查找
class School(object):
    school = '北京大学'

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


class Student(School):
    # 派生 : 派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找
    def __init__(self, name, age, sex):
        # 直接调用 父类 中 的 __init__ 方法
        # 调用的是绑定方法,因此会自动传入self,但是需要传入相应的参数
        super().__init__(name, age)
        self.sex = sex

    def read(self):
        print(f"{self.age}岁的{self.sex}学生{self.name}的学校是{self.school}")


# 只会找自己类中的__init__,并不会自动调用父类的
obj = Student('ligo', 18, '男')
print(obj.name, obj.sex, obj.age)
# ligo 男 18
obj.read()
# 18岁的男学生ligo的学校是北京大学

【3】小结

  • 这两种方式的区别是:
    • 方式一是跟继承没有关系的,而方式二的super()是依赖于继承的
    • 并且即使没有直接继承关系,super()仍然会按照MRO继续往后查找
#指名道姓
class A:
    def __init__(self):
        print('A的构造方法')
class B(A):
    def __init__(self):
        print('B的构造方法')
        A.__init__(self)


class C(A):
    def __init__(self):
        print('C的构造方法')
        A.__init__(self)


class D(B,C):
    def __init__(self):
        print('D的构造方法')
        B.__init__(self)
        C.__init__(self)

    pass
f1=D() #A.__init__被重复调用
'''
D的构造方法
B的构造方法
A的构造方法
C的构造方法
A的构造方法
'''
#使用super()
class A:
    def __init__(self):
        print('A的构造方法')
class B(A):
    def __init__(self):
        print('B的构造方法')
        super(B,self).__init__()


class C(A):
    def __init__(self):
        print('C的构造方法')
        super(C,self).__init__()


class D(B,C):
    def __init__(self):
        print('D的构造方法')
        super(D,self).__init__()

f1=D() #super()会基于mro列表,往后找
'''
D的构造方法
B的构造方法
C的构造方法
A的构造方法
'''

【二】组合

【1】什么是组合

  • 在一个类中以另外一个类的对象作为数据属性,称为类的组合

【2】组合的使用

class Course:
    def __init__(self, name, period, price):
        self.name = name
        self.period = period
        self.price = price

    def tell_info(self):
        print(f'当前课程名字 {self.name} 当前课程周期 {self.period} 当前课程价格 {self.price}')


class Date:
    def __init__(self, year, mon, day):
        self.year = year
        self.mon = mon
        self.day = day

    def tell_birth(self):
        print(f'当前生日 {self.year} 年 {self.mon} 月 {self.day} 日')


class People:
    school = '清华大学'

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


# Teacher类基于继承来重用People的代码
# 基于组合来重用Date类和Course类的代码
class Teacher(People):
    # 老师是人
    def __init__(self, name, sex, age, title, year, mon, day):
        super().__init__(name, age, sex)
        # 老师有生日
        self.birth = Date(year, mon, day)
        # 老师有课程,可以在实例化后,往该列表中添加Course类的对象
        self.courses = []

    def teach(self):
        print(f'当前老师正在授课 {self.name}')


python = Course('python', '3mons', 3000.0)
linux = Course('linux', '5mons', 5000.0)
teacher1 = Teacher('dream', 'male', 18, '金牌讲师', 1987, 3, 23)

# teacher1有两门课程
teacher1.courses.append(python)
teacher1.courses.append(linux)

# 重用Date类的功能
teacher1.birth.tell_birth()

# 重用Course类的功能
for obj in teacher1.courses:
    obj.tell_info()

# 当前生日 1987 年 3 月 23 日
# 当前课程名字 python 当前课程周期 3mons 当前课程价格 3000.0
# 当前课程名字 linux 当前课程周期 5mons 当前课程价格 5000.0

【3】组合和继承的区别

(1)继承的方式

  • 通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物
  • 当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如老师是人,学生是人

(2)组合的方式

  • 用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python和linux课程,教授有学生s1、s2、s3...
posted @ 2024-05-10 16:33  Ligo6  阅读(55)  评论(0)    收藏  举报