Python 编程基础 | 第五章-类 | 5.7、封装、继承与多态

一、继承与多态

面向对象编程(OOP)的三大特征,即:封装、继承、多态,下面主要讲解继承与多态

1、object类

在介绍继承与多态之前,先介绍下Python中的object类。在Python中object类是所有类的基类,所有的Python类都隐式地继承自object,如下:

class A:
    pass

print(A.__base__)  # 输出结果:<class 'object'>

官方参考文档:https://docs.python.org/zh-cn/3.9/library/functions.html?highlight=object#object

根据官方说法,调用o = object()会返回一个没有特征的新对象。object是所有类的基类。它具有所有 Python 类实例的通用方法,这个函数不接受任何实参,示例:

o = object()
print(o)  # 输出结果:<object object at 0x00EBF0F0>

没有特征的新对象是什么意思呢?它是指这个对象o没有任何自定义的属性或者方法,它只有一些object类提供的特殊方法。而且,不能给这个对象添加任何属性或者方法。官方文档中也有说明:由于object没有__dict__,因此无法将任意属性赋给 object 的实例

内置的dir方法列出对象的所有属性及方法,调用dir方法查看object类提供的全部属性,如下:

print(dir(object)) 
# 输出结果:['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

2、继承

通过继承可以继承父类的全部方法和属性,Python里面的继承有单继承多继承,格式如下:

# 派生类
class Derive(父类1, 父类2, ..., 父类n):
    pass

2.1、单继承

单继承,示例:

class Animal:
    def run(self):
        print('Animal is running...')

class Dog(Animal):
    def run(self):
        print('Dog is running...')

如果子类与父类的方法名、属性名相同,调用子类时默认使用子类的方法、属性

class Person:
    name = "person"

    def say(self):
        print(f"my name is {self.name}")

class Student(Person):
    name = "Student"

    def say(self):
        print(f"my name is {self.name}");

zhangsan = Student()
zhangsan.say()   # 输出结果:my name is Student

2.2、多继承

多继承,示例:

class P1():
    def talk(self):
        print("我是p1")

class P2():
    def talk(self):
        print("我是p2")

class Person(P1, P2): # P1排在第一位,调用P1的talk()
    pass

p = Person()
p.talk()              # 输出结果:我是p1

注意:如果派生类有多个父类,多个父类都有相同的方法,方法调用时是按照继承参数的顺序来的,谁排在第一个就调用谁的方法

3、多态

多态:即同一个接口根据访问的对象的不同而有不同的行为。继承时如果派生类的方法与基类同名,派生类的方法会覆盖基类的方法,由于这个特性才实现的多态,示例:

class Animal:
    def run(self):
        print('Animal is running...')

class Dog(Animal):
    def run(self):
        print('Dog is running...')

class Cat(Animal):
    def run(self):
        print('Cat is running...')

def run_twice(animal):
    animal.run()

my_animal = Animal()
my_dog = Dog()
my_cat = Cat()

run_twice(my_animal)   # 输出结果:Animal is running...
run_twice(my_dog)      # 输出结果:Dog is running...
run_twice(my_cat)      # 输出结果:Cat is running...

从输出结果可以看出来,run_twice函数里面调用的animal.run()函数,根据输入对象的不同(实际分别传入的是my_animal, my_dog, my_cat对象),分别有不同的输出结果。

多态存在的三个必要条件:

  • 有继承
  • 有重写,即:派生类重写基类的同名方法
  • 父类引用指向子类对象

4、查看继承关系

通过类属性__mro__可以查看类继承关系,如下:

class Person:
    name = "person"

    def say(self):
        print(f"my name is {self.name}")

class Student(Person):
    name = "Student"

    def say(self):
        print(f"my name is {self.name}")

print(Student.__mro__)  # 输出结果:(<class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>)

5、super方法

5.1、方法定义

通过super()方法可以调用父类或超类中的方法,方法声明如下:

super(type[, object-or-type])

参数解析:

  • type:类,可选参数
  • object-or-type:对象或类,一般是 self,可选参数

help 帮助信息:


>>> help(super)
Help on class super in module builtins:
 
class super(object)
 |  super() -> same as super(__class__, <first argument>)
 |  super(type) -> unbound super object
 |  super(type, obj) -> bound super object; requires isinstance(obj, type)
 |  super(type, type2) -> bound super object; requires issubclass(type2, type)
 |  Typical use to call a cooperative superclass method:
 |  class C(B):
 |      def meth(self, arg):
 |          super().meth(arg)
 |  This works for class methods too:
 |  class C(B):
 |      @classmethod
 |      def cmeth(cls, arg):
 |          super().cmeth(arg)
 
... ...

从官方的帮助文档可以看出

  • super 是一个继承自 object 的类,调用 super() 函数其实就是 super 类的实例化
  • 根据官方文档的解释 super() 函数返回的对象-super object,就是一个代理对象
  • super() 有四种参数的组合形式
  • super() 适用于类的静态方法

5.2、使用场景

使用super()方法主要解决下面这些问题

  • 在子类中调用父类的方法
  • 多用于多继承问题中,解决查找顺序(MRO)、重复调用(钻石继承)等种种问题
5.2.1、单继承场景

help() 的帮助信息中,也说明了类中使用 super()不带参数的形式等同于super(__class__, <first argument>) 这种形式,这也是 Python 2.x 和 Python 3.x 关于 super() 的区别,示例:子类调用父类方法

class A:
    def funxx(self):
        print("执行 A 中的 funxx 方法 ... ...")

class B(A):
    def funxx(self):
        # super(B,self) 首先找到 B 的父类(就是类 A),然后把类 B 的对象转换为类 A 的对象
        super().funxx()
        print("执行 B 中的 funxx 方法 ... ...")

b = B()
b.funxx()

输出结果:

执行 A 中的 funxx 方法 ... ...
执行 B 中的 funxx 方法 ... ...
5.2.2、多继承场景

https://blog.csdn.net/qq_41961087/article/details/117674563?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_utm_term~default-1-117674563-blog-82912808.pc_relevant_3mothn_strategy_recovery&spm=1001.2101.3001.4242.2&utm_relevant_index=4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值