22 派生与多态

1.派生

派生指的是子类继承父类属性,并且派生出自己的属性。
在进行属性查找时,子类中的属性名会优先于父类被查找。
对象中的的属性有相同的,可以将代码提出来建一个父类。

在子类派生方法内使用使用父类的功能,有两种方式:
1.指定名称
2.super()
# 案例
class Student():
    school = '桂电'

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

class Teacher():
    school = '桂电'
    def __init__(self, name, age, gender, title):

        self.name = name
        self.age = age
        self.gender = gender
        self.title = title
class GLIET:
    school = '桂电'

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
1.1指定名称
指定类的名称调用这个类中的属性。这种方式任何类都可以访问得到。
将类名称括号和父类名称删除断开继承关系,也可以访问得到这个功能。
不依赖于继承关系,使用时必须严格按照函数的要求传入值,这个self不能省略,否则缺少参数。
类名.__init__(self, 参数1, 参数2 ···)
class GLIET:
    school = '桂电'
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

class Student(GLIET):
    def __init__(self, name, age, gender, course):
        GLIET.__init__(self, name, age, gender)
        self.course = course

class Teacher(GLIET):
    def __init__(self, name, age, gender, title):
        GLIET.__init__(self, name, age, gender)
        self.title = title

stu1 = Student('kid', 18, 'male', 'python')     # {'name': 'kid', 'age': 18, 'gender': 'male', 'course': 'python'}
tea1 = Teacher('qz', 30, 'male', 'python')      # {'name': 'qz', 'age': 30, 'gender': 'male', 'title': 'python'}

print(stu1.__dict__)
print(tea1.__dict__)
1.2 super
调用super()会返回一个特殊的对象,该对象专门用来引用父类的属性,依赖于继承的关系,严格按照MRO的规定顺序向后查找。使用时会自动传入self参数,不能在写,否则参数多了。
Python 2 中: super(自己的类名, self).__init__( 参数1, 参数2 ···) 完整写法。
Python 3 中:  super().__init__( 参数1, 参数2 ···) 简写。
class GLIET:
    school = '桂电'
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

class Student(GLIET):
    def __init__(self, name, age, gender, course):
        super().__init__(name, age, gender)
        self.course = course

class Teacher(GLIET):
    def __init__(self, name, age, gender, title):
        super().__init__( name, age, gender)
        self.title = title

stu1 = Student('kid', 18, 'male', 'python')     # {'name': 'kid', 'age': 18, 'gender': 'male', 'course': 'python'}
tea1 = Teacher('qz', 30, 'male', 'python')      # {'name': 'qz', 'age': 30, 'gender': 'male', 'title': 'python'}

print(stu1.__dict__)
print(tea1.__dict__)
# 查找顺序
class A:
    def test(self):
        print("A----text")
        print(super())
        super().aaa()
        print(111)

        def aaa(self):
            print('B----aaa')

    def aaa(self):
        print('B----aaa')

class B:
    def test(self):
        print("B----text")

    def aaa(self):
        print("B----aaa")

class C(A, B):
    def aaa(self):
        print('C----->aaa')
super()只会按照MRO列表的顺序查找,不会在回头查找。
A----text
<super: <class 'A'>, <C object>>    # A.aaa() 从下面的MRO列表可以看出
B----aaa                            # 往前查找
A----aaa                            # 回头
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]

2.组合

在一个类中以另外一个类的对象作为数据属性,称为类的组合。
代码复用:在编程过程中为了提高代码效率,将重复的代码提炼成可复用的代码,而降低代码的复写。子类通过继承父类,而复用父类代码。
解决类与类之间的冗余问题:
	1.继承:是一种什么是什么的关系,两个类中有共同的属性。
	2.组合:是一种什么有什么的关系,不需要依赖什么相关联的。
在类与类有关系用的情况使用继承,在没有关系的情况下用组合。
# 例1
class Foo():
    def __init__(self, x):
        self.x = x
    def func1(self):
        return self.x

class Bar():
    def __init__(self, y):
        self.y = y
    def func1(self):
        return self.y

obj1 = Foo(10)
obj2 = Bar(20)

obj1.z = obj2                                      # 对象的属性是另一个对象
print(obj1.z.y)                                    # 20
# 例2
class GLIET():   # 派生属性
    school = '桂电'
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

class Course():    # 课程信息
    def __init__(self, course_name, course_period, course_price):
        self.course_name = course_name
        self.course_period = course_period
        self.course_price = course_price

class Student(GLIET):   # 学生

    def __init__(self, name, age, gender, courses=None):
        if courses == None:
            courses = []
        self.courses = courses
        super().__init__(name, age, gender)

    def choose_course(self, course):         # 学生能选课
        self.courses.append(course)
        print("%s 选课成功%s" % (self.name, course.course_name))

class Teacher(GLIET):  # 老师
    def __init__(self, name, age, gender, teach):
        super().__init__(name, age, gender)
        self.teach = teach

    def performance(self, stu_obj, num):   # 老师给成绩
        stu_obj.num = num
        print("%s老师给%s学生打分%s." % (self.name, stu_obj.name, num))


python = Course('Python', '6month', 21000)   # 课程 六个月  学费

stu1 = Student('kid', 18, 'male')            # 使用继承派生出自己的属性
stu1.choose_course(python)                   # 组合选课程

tea1 = Teacher('qz', 30, 'male', python)
tea1.performance(stu1, 85)
print(tea1.teach.course_name)               # 组合

3.多态性

多态指的是在子类中复写父类的方法。
这样做的好处是:同样名称的方法在不同的子类中会有不同的行为。但是它们有相同的特征,可以使用相同的方法来访问它们。
class Animal():
    def talk(self):
        print('嘿嘿')

class Cat(Animal):
    def talk(self):
        print('喵')

class Dog(Animal):
    def talk(self):
        print('汪')

class Duck(Animal):
    def talk(self):
        print('噶')

cat = Cat()
dog = Dog()
duck = Duck()

cat.talk()
dog.talk()
duck.talk()

3.1多态性

把对象的使用方法统一,做为接口,调用一个接口函数,传入不同的参数,可以达到不同的功能,一个接口多种实现。
# 多态性应用
class Animal():
    def talk(self):
        print('嘿嘿')

class Cat(Animal):
    def talk(self):
        print('喵')

class Dog(Animal):
    def talk(self):
        print('汪')

class Duck(Animal):
    def talk(self):
        print('噶')

def talk(obj):
    obj.talk()

cat = Cat()
dog = Dog()
duck = Duck()

talk(cat)
talk(dog)
talk(duck)
Python中一切皆对象,本身就支持多态性。
'sasada'.__len__()
{'k1': 1}.__len__()
[1, 2, 3].__len__()
len('sasada')
len({'k1': 1})
len([1, 2, 3])
多态性的本质在不同的类中定义有相同的方法名称,可以在父类中限制子类中必须有某些方法名称实现相对应的功能。
import abc
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod  # 装饰器现在子类中必须定义talk方法。
    def talk(self):      # 抽象方法,功能自己写去吧,我不管。
        pass
class Cat(Animal):
    pass

cat = Cat()               # Cat类中没有talk方法直接报错。
class Cat(Animal):
    def talk(self):       # 符合父类的要求
        print('喵')

cat = Cat()

4.鸭子类型

Python崇尚鸭子类型,如果看起来像,叫声也像,走路也像鸭子,那么他就是鸭子。
对接口函数,传入不同的参数,只要这个参数中有相同的属性即可。
class Animal:
    def talk(self):
        print('嘿嘿')
        
class Cat(Animal):
    def talk(self):
        print('喵')

class Dog(Animal):
    def talk(self):
        print('汪')

class Duck(Animal):
    def talk(self):
        print('噶')

class Phone(object):      # 我做鸭子了
    def talk(self):
        print('支付宝到账100块')


def talk(obj):
    obj.talk()

cat = Cat()
dog = Dog()
duck = Duck()
phone = Phone()

talk(cat)
talk(dog)
talk(duck)
talk(phone)
使用一个talk()函数来访问Animal子类的相同方法,但对函数来说传入的值不管是什么,只要有它内部执行的这个方法即可。它不依赖继承关系,只要这样对象看起来像鸭子,走起来像鸭子就可以把它当作鸭子。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值