Python如何定义接口和抽象类


Posted in Python onJuly 28, 2020

问题

你想定义一个接口或抽象类,并且通过执行类型检查来确保子类实现了某些特定的方法

解决方案

使用 abc 模块可以很轻松的定义抽象基类:

from abc import ABCMeta, abstractmethod

class IStream(metaclass=ABCMeta):
  @abstractmethod
  def read(self, maxbytes=-1):
    pass

  @abstractmethod
  def write(self, data):
    pass

抽象类的一个特点是它不能直接被实例化,比如你想像下面这样做是不行的:

a = IStream() # TypeError: Can't instantiate abstract class
        # IStream with abstract methods read, write

抽象类的目的就是让别的类继承它并实现特定的抽象方法:

class SocketStream(IStream):
  def read(self, maxbytes=-1):
    pass

  def write(self, data):
    pass

抽象基类的一个主要用途是在代码中检查某些类是否为特定类型,实现了特定接口:

def serialize(obj, stream):
  if not isinstance(stream, IStream):
    raise TypeError('Expected an IStream')
  pass

除了继承这种方式外,还可以通过注册方式来让某个类实现抽象基类:

import io

# Register the built-in I/O classes as supporting our interface
IStream.register(io.IOBase)

# Open a normal file and type check
f = open('foo.txt')
isinstance(f, IStream) # Returns True

@abstractmethod 还能注解静态方法、类方法和 properties 。 你只需保证这个注解紧靠在函数定义前即可:

class A(metaclass=ABCMeta):
  @property
  @abstractmethod
  def name(self):
    pass

  @name.setter
  @abstractmethod
  def name(self, value):
    pass

  @classmethod
  @abstractmethod
  def method1(cls):
    pass

  @staticmethod
  @abstractmethod
  def method2():
    pass

讨论

标准库中有很多用到抽象基类的地方。collections 模块定义了很多跟容器和迭代器(序列、映射、集合等)有关的抽象基类。 numbers 库定义了跟数字对象(整数、浮点数、有理数等)有关的基类。io 库定义了很多跟I/O操作相关的基类。

你可以使用预定义的抽象类来执行更通用的类型检查,例如:

import collections

# Check if x is a sequence
if isinstance(x, collections.Sequence):
...

# Check if x is iterable
if isinstance(x, collections.Iterable):
...

# Check if x has a size
if isinstance(x, collections.Sized):
...

# Check if x is a mapping
if isinstance(x, collections.Mapping):

尽管ABCs可以让我们很方便的做类型检查,但是我们在代码中最好不要过多的使用它。 因为Python的本质是一门动态编程语言,其目的就是给你更多灵活性, 强制类型检查或让你代码变得更复杂,这样做无异于舍本求末。

以上就是Python如何定义接口和抽象类的详细内容,更多关于Python定义接口和抽象类的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python实现同时兼容老版和新版Socket协议的一个简单WebSocket服务器
Jun 04 Python
Python处理字符串之isspace()方法的使用
May 19 Python
详解Python中contextlib上下文管理模块的用法
Jun 28 Python
浅谈编码,解码,乱码的问题
Dec 30 Python
Python网络编程详解
Oct 31 Python
Python模拟随机游走图形效果示例
Feb 06 Python
20个常用Python运维库和模块
Feb 12 Python
Pandas 对Dataframe结构排序的实现方法
Apr 10 Python
Ubuntu下Python2与Python3的共存问题
Oct 31 Python
python os.fork() 循环输出方法
Aug 08 Python
python实现多线程端口扫描
Aug 31 Python
Python单链表原理与实现方法详解
Feb 22 Python
Python爬虫之爬取淘女郎照片示例详解
Jul 28 #Python
Python selenium键盘鼠标事件实现过程详解
Jul 28 #Python
用python写爬虫简单吗
Jul 28 #Python
公认8个效率最高的爬虫框架
Jul 28 #Python
python如何爬取网页中的文字
Jul 28 #Python
Python同时处理多个异常的方法
Jul 28 #Python
Python远程方法调用实现过程解析
Jul 28 #Python
You might like
利用PHP动态生成VRML网页
2006/10/09 PHP
php获取bing每日壁纸示例分享
2014/02/25 PHP
getJSON跨域SyntaxError问题分析
2014/08/07 PHP
PHP实现数组转JSon和JSon转数组的方法示例
2018/06/14 PHP
解决在laravel中leftjoin带条件查询没有返回右表为NULL的问题
2019/10/15 PHP
php 多继承的几种常见实现方法示例
2019/11/18 PHP
基于jQuery的投票系统显示结果插件
2011/08/12 Javascript
cument.execCommand()用法深入理解
2012/12/04 Javascript
JQuery切换显示的效果实例代码
2013/02/27 Javascript
jquery仿京东导航/仿淘宝商城左侧分类导航下拉菜单效果
2013/04/24 Javascript
利用js实现遮罩以及弹出可移动登录窗口
2013/07/08 Javascript
js函数模拟显示桌面.scf程序示例
2014/04/20 Javascript
js全选实现和判断是否有复选框选中的方法
2015/02/17 Javascript
js+jquery常用知识点汇总
2015/03/03 Javascript
JavaScript 对象深入学习总结(经典)
2015/09/29 Javascript
JS实现新浪微博效果带遮罩层的弹出框代码
2015/10/12 Javascript
JS正则子匹配实例分析
2016/12/22 Javascript
基于D3.js实现时钟效果
2018/07/17 Javascript
解决vue2.0路由跳转未匹配相应用路由避免出现空白页面的问题
2018/08/24 Javascript
浅谈Fetch 数据交互方式
2018/12/20 Javascript
Node.js操作MongoDB数据库实例分析
2020/01/19 Javascript
NodeJS多种创建WebSocket监听的方式(三种)
2020/06/04 NodeJs
Python中for循环详解
2014/01/17 Python
使用python实现生成用户信息
2017/03/20 Python
python爬虫实战之爬取京东商城实例教程
2017/04/24 Python
Windows下Anaconda2安装NLTK教程
2018/09/19 Python
python微信撤回监测代码
2019/04/29 Python
解决Pytorch自定义层出现多Variable共享内存错误问题
2020/06/28 Python
Pycharm 设置默认解释器路径和编码格式的操作
2021/02/05 Python
使用HTML5 Canvas为图片填充颜色和纹理的教程
2016/03/21 HTML / CSS
大学生职业规划论文
2014/01/11 职场文书
消防安全检查制度
2014/02/04 职场文书
2014年9.18纪念日演讲稿
2014/09/14 职场文书
详解Redis集群搭建的三种方式
2021/05/31 Redis
一篇文章搞懂python混乱的切换操作与优雅的推导式
2021/08/23 Python
特别篇动画《总之就是非常可爱 ~制服~》PV公开,2022年夏季播出
2022/04/04 日漫