python面试题——抽象基类和接口

在这里插入图片描述

一、抽象基类与接口

1、抽象基类(abstract base class,ABC)

提到这个概念,我们应该会马上联想到面向对象、继承。作为继承的一种,它拥有继承中代码共享、提高代码的重用性等优点。例如:

class Animal(object):
    def eat(self):
        print('吃饭')

class Dog(Animal):
    pass

class Cat(Animal):
    pass


animal=Animal()
animal.eat()

dog=Dog()
dog.eat()

cat=Cat()
cat.eat()

输出:
吃饭
吃饭
吃饭

狗(Dog)和猫(Cat)都属于动物(Animal),它们有很多类似的属性和动作,我们可以在父类中实现这些方法,在子类中直接继承或者重写父类中的方法,这样减少了代码的重复性,提高了代码的复用能力。

作为继承的一种,抽象基类有用继承的上述这些优点,但是它与普通的继承也有不同之处,
抽象基类不能实例化
子类需要实现基类指定的抽象方法

看到这里,我们会感觉抽象基类有一种接口的感觉。

抽象基类的主要是功能就是类似于Java等编程语言中的接口。但是需要明确一点,Python语言中没有interface这个概念,这只是一种约定俗成的编程规范,就如同Python也没有真实意义上的私有变量,我们在编程中可以规范的使用下划线来表示某个变量为私有变量。

2、接口

接口(Interface)是对象公开方法的一种集合,在Java中通常以interface关键字来定义,接口虽然实现过程中和类相似,但是却具有不同的概念。具体而言,类与接口主要有以下几点不同之处:

类实现了对象的属性和方法,而接口指定了使用该接口需要实现哪些方法
类可以实例化,而接口不可以被实例化
类中的方法可以是实现,接口中的方法都是抽象方法

3、抽象基类的实现

Python标准库中有一个模块abc可以实现抽象基类和抽象方法,它们的实现方式如下:

4、特别注意

抽象基类 :通过继承abc模块中的ABC类来实现抽象基类。
抽象方法 :通过装饰器abstractmethod来声明抽象方法。

含有abstractmethod的类不能被实例化,集成了含abstractmethod方法的子类必须包含(重写)abstractmethod装饰的方法,没有被装饰的可以不重写。

1、例如,定义一个飞机的抽象基类

from abc import ABC,abstractmethod


#定义一个飞机的抽象基类
#抽象基类是不能直接被实例化的
class AirPlane(ABC):

    @abstractmethod
    def fly(self):
        pass

    @abstractmethod
    def oil(self):
        pass

class FightPlane(AirPlane):
    def __init__(self,name):
        self.name=name

    def shoot(self):
        print(self.name,'攻击')

class TransPlane(AirPlane):
    def __init__(self,name):
        self.name=name

    def load(self):
        print(self.name,'攻击')

if __name__ == '__main__':


    plane_b=FightPlane('战斗机')
    plane_b.shoot()


    plane_c=TransPlane('运输机')
    plane_c.load()

报错:

plane_a=AirPlane()
TypeError: Can't instantiate abstract class AirPlane with abstract methods fly, oil

2、例如,定义战斗机和运输机并且继承飞机的抽象基类

from abc import ABC,abstractmethod


#定义一个飞机的抽象基类
#抽象基类是不能直接被实例化的
class AirPlane(ABC):

    @abstractmethod
    def fly(self):
        pass

    @abstractmethod
    def oil(self):
        pass

class FightPlane(AirPlane):
    def __init__(self,name):
        self.name=name

class TransPlane(AirPlane):
    def __init__(self,name):
        self.name=name

if __name__ == '__main__':


    plane_b=FightPlane('战斗机')
    plane_b.shoot()

    plane_c=TransPlane('运输机')
    plane_c.load()

执行结果:

plane_b=FightPlane('战斗机')
TypeError: Can't instantiate abstract class FightPlane with abstract methods fly, oil

3、例如,定义战斗机和运输机重写基类中的抽象方法并且继承飞机的抽象基类

from abc import ABC,abstractmethod


#定义一个飞机的抽象基类
#抽象基类是不能直接被实例化的
class AirPlane(ABC):

    @abstractmethod
    def fly(self):
        pass

    @abstractmethod
    def oil(self):
        pass

class FightPlane(AirPlane):
    def __init__(self,name):
        self.name=name
	# 必须要实现抽象基类的抽象方法,不然实例化会报错
    def fly(self):
        print(self.name, '飞行')
	# 必须要实现抽象基类的抽象方法,不然实例化会报错
    def oil(self):
        print(self.name, '加油')
	#自己的方法
    def shoot(self):
        print(self.name,'攻击')

class TransPlane(AirPlane):
    def __init__(self,name):
        self.name=name
	# 必须要实现抽象基类的抽象方法,不然实例化会报错
    def fly(self):
        print(self.name, '飞行')
	# 必须要实现抽象基类的抽象方法,不然实例化会报错
    def oil(self):
        print(self.name, '加油')
	#自己的方法
    def load(self):
        print(self.name,'攻击')

if __name__ == '__main__':


    plane_b=FightPlane('战斗机')
    plane_b.shoot()


    plane_c=TransPlane('运输机')
    plane_c.load()

输出:

战斗机 攻击
运输机 攻击

在这里插入图片描述

在这里插入图片描述

  • 44
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 74
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

敲代码敲到头发茂密

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值