python之抽象类&abc模块+虚拟子类®ister
抽象类和接口:
java
我们先从java讲起,没有java基础的可以略过。
(挖坑)
python
在python并没有抽象类之说,或者说抽象类=接口类(区别于接口)
继承有两种用途:
一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)
二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能
在python中实现接口类必须借助于 abc模块
abc模块
前言:
面向对象的设计中,抽象类,接口这些必不可少的东西,在python中是如何提现的呢?
python作为一个动态语言,没有强类型的检查,而是以鸭子类型的方式提现,在执行的时候python不严格要求你必须是继承指定的父类而来,只要在调用的时候你有相应的方法和属性就可以了,长的像鸭子你就是鸭子。
也正是基于python这样的特性,python中没有interface的概念。
interface并不是普遍存在的,而是作为一个特例出现在java中,为的是解决多继承的问题。
python支持多继承,自然没有这个需要了。
然而我们难免会有这样的需求:子类必须实现某些指定的方法和属性,否则就抛异常。使用一些笨方法自然是可以达到相同的效果,但是python为我们提供了abc模块。
what is abc:
import abc
print([i for i in dir(abc) if not i.startswith("__")])
['ABC', 'ABCMeta', 'WeakSet', 'abstractclassmethod', 'abstractmethod', 'abstractproperty', 'abstractstaticmethod', 'get_cache_token']
How use abc?
竟然没报错?
from abc import ABCMeta, abstractmethod
class Drawable(metaclass=ABCMeta):
# @abstractmethod
def size(self):
return 'Drawable size'
# @abstractmethod
def draw(self, x, y, scale=1.0):
pass
def double_draw(self, x, y):
self.draw(x, y, scale=2.0)
d=Drawable()
说明。这个接口类竟然可以实例化。
接下来,我们给这个接口类添加一个abstractmethod方法的时候
class Drawable(metaclass=ABCMeta):
@abstractmethod
def size(self):
return 'Drawable size'
# @abstractmethod
def draw(self, x, y, scale=1.0):
pass
def double_draw(self, x, y):
self.draw(x, y, scale=2.0)
d=Drawable()
它报错了:TypeError: Can't instantiate abstract class Drawable with abstract methods size
总结:有抽象方法的接口类才是不能实例化。
接下来,我们继续看继承关系
from abc import ABCMeta, abstractmethod
class Drawable(metaclass=ABCMeta):
# @abstractmethod
def size(self):
return 'Drawable size'
# @abstractmethod
def draw(self, x, y, scale=1.0):
pass
def double_draw(self, x, y):
self.draw(x, y, scale=2.0)
class Cicle(Drawable):
# def size(self):
# return 'Cicle size'
# def draw(self, x, y, scale=1.0):
# print(x * scale, y * scale)
def paint(self):
pass
c=Cicle()
成功了。=》告诉我们继承一个没有抽象方法的接口类,并不用重写也能实例化。毕竟没有抽象方法。
那有抽象方法的接口类呢?
1.继承有抽象方法的接口类但没有重写抽象方法=》报错
from abc import ABCMeta, abstractmethod
class Drawable(metaclass=ABCMeta):
@abstractmethod
def size(self):
return 'Drawable size'
# @abstractmethod
def draw(self, x, y, scale=1.0):
pass
def double_draw(self, x, y):
self.draw(x, y, scale=2.0)
class Cicle(Drawable):=====》继承但没有实现抽象方法
def paint(self):
pass
c=Cicle()
TypeError: Can't instantiate abstract class Cicle with abstract methods size
2,继承有抽象方法的接口类必须重写抽象方法
from abc import ABCMeta, abstractmethod
class Drawable(metaclass=ABCMeta):
@abstractmethod
def size(self):
return 'Drawable size'
# @abstractmethod
def draw(self, x, y, scale=1.0):
pass
def double_draw(self, x, y):
self.draw(x, y, scale=2.0)
class Cicle(Drawable):
def size(self):
return 'Cicle size'
def paint(self):
pass
c=Cicle()
成功了
3.继承有抽象方法的非接口类呢?
from abc import ABCMeta, abstractmethod
class Drawable:
@abstractmethod
def size(self):
return 'Drawable size'
# @abstractmethod
def draw(self, x, y, scale=1.0):
pass
def double_draw(self, x, y):
self.draw(x, y, scale=2.0)
class Cicle(Drawable):
def paint(self):
pass
c=Cicle()
成功====》单独存在抽象方法并没啥用
进阶:
1.ABC是python 3.4之后新增的类,之前必须使用metaclass=ABCMeta,现在多了一个简单的方法ABC
2.abc模块还定义了'abstractclassmethod', 'abstractproperty', 'abstractstaticmethod'三个装饰器,但是因为可以通过@abstractmethod上堆叠实现,就显得多余二废弃了。
from abc import *
class A(ABC):
@property
@abstractmethod
def func(self):
pass
@abstractproperty
def func2(self):
pass
@classmethod
@abstractmethod
def func3(cls):
pass
@abstractclassmethod
def func4(cls):
pass
@staticmethod
@abstractmethod
def func5():
pass
@abstractstaticmethod
def func6():
pass
虚拟子类
注册虚拟子类的方式在抽象基类上调用register方法
注册的类就会变成抽象基类的虚拟子类,而且issubclass和isinstance等函数都能识别,但是注册的类并不会从抽象基类中继承任何方法。
虚拟子类不会继承注册的抽象基类,而且任何时候都不会检查子类是否符合抽象基类的接口(即使在实例化的时候也不会检查)。
作为抽象类的虚拟子类无需实现其需要的抽象方法
from abc import *
class A(metaclass=ABCMeta):
@abstractmethod
def func1(self):
pass @A.register
class B:
def func2(self):
pass class C(A):
def func2(self):
pass b=B() #===》作为抽象类的虚拟子类无需实现其需要的抽象方法
# c=C()==>继承抽象类没有实现抽象方法报错
print("OK")
类的继承关系在一个特殊属性中制定--__mro__即方法解析顺序,这个属性会按顺序列出所有 ‘真实的’ 类和其超类。
from abc import *
class A(ABC):
@abstractmethod
def func1(self):
pass class B:
def func1(self):
pass @A.register
class C(B):
def func2(self):
pass b=B()
c=C()
print(issubclass(C,A))
print(isinstance(c,A))
print(isinstance(c,B))
# True
# True
# True print(C.__mro__)
# (<class '__main__.C'>, <class '__main__.B'>, <class 'object'>)
# 没有A类
python之抽象类&abc模块+虚拟子类®ister的更多相关文章
- python abc模块
面向对象的设计中,抽象类,接口这些必不可少的东西,在python中是如何提现的呢? python作为一个动态语言,没有强类型的检查,而是以鸭子类型的方式提现,在执行的时候python不严格要求你必须是 ...
- Python装饰器、metaclass、abc模块学习笔记
(博客原创作品,转载请注明出处!) 最近接触到了Python中的decorator,metaclass,abc Module,six.add_metaclass等内容,这里做一个简单的笔记. 主要资源 ...
- 第7.21节 Python抽象类—register注册虚拟子类
上两节介绍了Python抽象类的真实子类的定义和使用,本节介绍另一种抽象类的实现方法:虚拟子类方法. 一. 相关概念 虚拟子类是将其他的不是从抽象基类派生的类"注册"到抽象基 ...
- 第7.19节 Python中的抽象类详解:abstractmethod、abc与真实子类
第7.19节 Python中的抽象类详解:abstractmethod.abc与真实子类 一. 引言 前面相关的章节已经介绍过,Python中定义某种类型是以实现了该类型对应的协议为标准的,而不 ...
- Python抽象类(abc模块)
1.抽象类概念 抽象类是一个特殊的类,只能被继承,不能实例化 2.为什么要有抽象类 其实在未接触抽象类概念时,我们可以构造香蕉.苹果.梨之类的类,然后让它们继承水果这个基类,水果的基类包含一个eat函 ...
- 学习Python的ABC模块(转)
http://yansu.org/2013/06/09/learn-Python-abc-module.html 1.abc模块作用 Python本身不提供抽象类和接口机制,要想实现抽象类,可以借助a ...
- 001学习Python的ABC模块(转)
http://yansu.org/2013/06/09/learn-Python-abc-module.html 1.abc模块作用 Python本身不提供抽象类和接口机制,要想实现抽象类,可以借助a ...
- Python基础-接口与归一化设计、抽象类、继承顺序、子类调用父类,多态与多态性
一.接口与归一化设计 Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能). 由 ...
- python基础——抽象类
python基础--抽象类 1 什么是抽象类 与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化 2 为什么要有抽象 ...
随机推荐
- jqGrid清空表格
$("#jqGrid").jqGrid("setGridParam",{ datatype:'local', data : [], page:1 }).trig ...
- nginx 开启gzip压缩
Nginx开启Gzip压缩功能, 可以使网站的css.js .xml.html 文件在传输时进行压缩,提高访问速度,! Web网站上的图片,视频等其它多媒体文件以及大文件,因为压缩效果不好,所以对于 ...
- lua table 的操作(四)
table在前面作过介绍,它是一种关联数组,这种关联指的是可以设置各类类型的key来存储值. 1.table 间的数据传递 -- 为 table a 并设置元素,然后将 a 赋值给 b,则 a 与 b ...
- 什么是Metrics-(通俗易懂)
在应用程序中,通常会记录日志以便事后分析,在很多情况下是产生了问题之后,再去查看日志,是一种事后的静态分析.在很多时候,我们可能需要了解整个系统在当前,或者某一时刻运行的情况,比如一个系统后台服务,我 ...
- [转帖]Linux日期和时间的那些事儿
Linux日期和时间的那些事儿 http://embeddedlinux.org.cn/emb-linux/entry-level/201311/09-2672.html 自己还是稚嫩啊.. 除了年龄 ...
- 安装matplotlib,报错ERROR: Command errored out with exit status 1:
使用pip install matplotlib 出现报错信息: 发现这行报错 : 我是在pycharm上安装的,可是提示我去安装 Microsoft Visual C++ ,然后去百度查了下,发现只 ...
- 用python库openpyxl操作excel,从源excel表中提取信息复制到目标excel表中
现代生活中,我们很难不与excel表打交道,excel表有着易学易用的优点,只是当表中数据量很大,我们又需要从其他表册中复制粘贴一些数据(比如身份证号)的时候,我们会越来越倦怠,毕竟我们不是机器,没法 ...
- Django 在Python3.5 下报 没有模块MySQLdb
在整个项目站点下的__init__.py 文件里(即和setting.py在同一个文件下)写入以下代码: import pymysql pymysql.install_as_MySQLdb() 需要提 ...
- 一文看懂java io系统 (转)
出处: 一文看懂java io系统 学习java IO系统,重点是学会IO模型,了解了各种IO模型之后就可以更好的理解java IO Java IO 是一套Java用来读写数据(输入和输出)的A ...
- 第四章 MIZ701 ZYNQ制作UBOOT固化程序
4.0难度系数★☆☆☆☆☆☆ 4.1是什么是固化 我们前几章将的程序都是通过JTAG先下载bit流文件,再下载elf文件,之后点击Run As来运行的程序.JTAG的方法是通过TCL脚本来初始化P ...