在Python中定义和使用抽象类的方法

https://www.jb51.net/article/87710.htm

 

像java一样python也可以定义一个抽象类。

在讲抽象类之前,先说下抽象方法的实现。

抽象方法是基类中定义的方法,但却没有任何实现。在java中,可以把方法申明成一个接口。而在python中实现一个抽象方法的简单的方法是:

?
1
2
3
class Sheep(object):
  def get_size(self):
    raise NotImplementedError

任何从Sheep继承下来的子类必须实现get_size方法。否则就会产生一个错误。但这种实现方法有个缺点。定义的子类只有调用那个方法时才会抛错。这里有个简单方法可以在类被实例化后触发它。使用python提供的abc模块。

?
1
2
3
4
5
6
7
import abc
class Sheep(object):
  __metaclass__ = abc.ABCMeta
   
  @abc.absractmethod
  def get_size(self):
    return


这里实例化Sheep类或任意从其继承的子类(未实现get_size)时候都会抛出异常。

因此,通过定义抽象类,可以定义子类的共同method(强制其实现)。

如何使用抽象类

?
1
2
3
4
5
6
7
8
9
10
11
12
import abc
class A(object):
  __metaclass__ = abc.ABCMeta
  @abc.abstractmethod
  def load(self, input):
    return
  @abc.abstractmethod
  def save(self, output, data):
    return

通过ABCMeta元类来创建一个抽象类, 使用abstractmethod装饰器来表明抽象方法

注册具体类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
class B(object):
   
  def load(self, input):
    return input.read()
  def save(self, output, data):
    return output.write(data)
A.register(B)
if __name__ == '__main__':
  print issubclass(B, A)   # print True
  print isinstance(B(), A)  # print True

从抽象类注册一个具体的类

子类化实现

?
1
2
3
4
5
6
7
8
9
10
11
class C(A):
  def load(self, input):
    return input.read()
  def save(self, output, data):
    return output.write(data)
     
if __name__ == '__main__':
  print issubclass(C, A)   # print True
  print isinstance(C(), A)  # print True

可以使用继承抽象类的方法来实现具体类这样可以避免使用register. 但是副作用是可以通过基类找出所有的具体类

?
1
2
3
4
for sc in A.__subclasses__():
  print sc.__name__
# print C

如果使用继承的方式会找出所有的具体类,如果使用register的方式则不会被找出

使用__subclasshook__

使用__subclasshook__后只要具体类定义了与抽象类相同的方法就认为是他的子类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import abc
class A(object):
  __metaclass__ = abc.ABCMeta
  @abc.abstractmethod
  def say(self):
    return 'say yeah'
  @classmethod
  def __subclasshook__(cls, C):
    if cls is A:
      if any("say" in B.__dict__ for B in C.__mro__):
        return True
    return NotTmplementd
class B(object):
  def say(self):
    return 'hello'
print issubclass(B, A)   # True
print isinstance(B(), A)  # True
print B.__dict__      # {'say': <function say at 0x7f...>, ...}
print A.__subclasshook__(B) # True

不完整的实现

?
1
2
3
4
5
6
7
class D(A):
  def save(self, output, data):
    return output.write(data)
if __name__ == '__main__':
  print issubclass(D, A)   # print True
  print isinstance(D(), A)  # raise TypeError

如果构建不完整的具体类会抛出D不能实例化抽象类和抽象方法

具体类中使用抽象基类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import abc
from cStringIO import StringIO
class A(object):
  __metaclass__ = abc.ABCMeta
  @abc.abstractmethod
  def retrieve_values(self, input):
    pirnt 'base class reading data'
    return input.read()
class B(A):
  def retrieve_values(self, input):
    base_data = super(B, self).retrieve_values(input)
    print 'subclass sorting data'
    response = sorted(base_data.splitlines())
    return response
input = StringIO("""line one
line two
line three
""")
reader = B()
print reader.retrieve_values(input)

打印结果

?
1
2
3
base class reading data
subclass sorting data
['line one', 'line two', 'line three']

可以使用super来重用抽象基类中的罗辑, 但会迫使子类提供覆盖方法.

抽象属性

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import abc
class A(object):
  __metaclass__ = abc.ABCMeta
  @abc.abstractproperty
  def value(self):
    return 'should never get here.'
class B(A):
   
  @property
  def value(self):
    return 'concrete property.'
try:
  a = A()
  print 'A.value', a.value
except Exception, err:
  print 'Error: ', str(err)
b = B()
print 'B.value', b.value

打印结果,A不能被实例化,因为只有一个抽象的property getter method.

?
1
2
Error: ...
print concrete property

定义抽象的读写属性

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import abc
class A(object):
  __metaclass__ = abc.ABCMeta
  def value_getter(self):
    return 'Should never see this.'
  def value_setter(self, value):
    return
  value = abc.abstractproperty(value_getter, value_setter)
class B(A):
   
  @abc.abstractproperty
  def value(self):
    return 'read-only'
class C(A):
  _value = 'default value'
  def value_getter(self):
    return self._value
  def value_setter(self, value):
    self._value = value
  value = property(value_getter, value_setter)
try:
  a = A()
  print a.value
except Exception, err:
  print str(err)
try:
  b = B()
  print b.value
except Exception, err:
  print str(err)
c = C()
print c.value
c.value = 'hello'
print c.value

打印结果, 定义具体类的property时必须与抽象的abstract property相同。如果只覆盖其中一个将不会工作.

?
1
2
3
4
error: ...
error: ...
print 'default value'
print 'hello'

使用装饰器语法来实现读写的抽象属性, 读和写的方法应该相同.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import abc
class A(object):
  __metaclass__ = abc.ABCMeta
  @abc.abstractproperty
  def value(self):
    return 'should never see this.'
  @value.setter
  def value(self, _value):
    return
class B(A):
  _value = 'default'
  @property
  def value(self):
    return self._value
  @value.setter
  def value(self, _value):
    self._value = _value
b = B()
print b.value    # print 'default'
b.value = 'hello'
print b.value    # print 'hello'

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/537905.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

把 Rational Rose 的图表保存为图片文件

原文连接&#xff1a;https://blog.csdn.net/xiaobing_122613/article/details/56485456 ------------------------------------------------ Rational Rose 本身没有保存为 JPG/GIF 图片格式的功能。 1. 可以通过全选、复制、粘贴可以把图表直接粘贴到打开的 Word 文档里 …

lppl模型 matlab,对LPPL模型的思考

2013-05-10 16:19:29最近&#xff0c;LPPL模型在金融市场中的运用越来越广&#xff0c;LPPL模型认为金融市场处于自组织临界状态&#xff0c;泡沫的产生往往伴随着市场参与者之间行为的正反馈作用&#xff0c;泡沫也会因此越来越大&#xff0c;并在奇点处崩溃&#xff0c;详细介…

代码质量管理工具】——sonar

原文地址&#xff1a;https://blog.csdn.net/luckystar689/article/details/53871821 ------------------------------------------------------------------------ 【前言】 bug越改越多&#xff0c;程序一换数据就崩&#xff0c;这就是目前我们系统的一个现状。在这之前&am…

马凯军201771010116《面向对象程序设计(java)》第二周学习总结

第一部分&#xff1a;理论知识学习部分 &#xff08;1&#xff09;基本知识&#xff1a;简单应用程序的结构&#xff1b;Java环境里的注释方式&#xff1b; &#xff08;2&#xff09;数据类型&#xff08;4种整型、2种浮点型、1种字符型‘char’、真值型‘Boolean’。 &#x…

【代码质量管理工具】-由sonar引发的思考

原文路径&#xff1a;https://blog.csdn.net/luckystar689/article/details/53968102 ---------------------------------------------------------------------------------------- 之前&#xff0c;在看《笑傲江湖》的时候&#xff0c;郭德纲在给一对夫妻的表演做评审的时候…

php curl 模拟多线程,php利用curl 多线程 模拟 并发的详解

php利用curl 多线程 模拟 并发的详解发布于 2014-12-07 10:17:25 | 265 次阅读 | 评论: 0 | 来源: 网友投递PHP开源脚本语言PHP(外文名: Hypertext Preprocessor&#xff0c;中文名&#xff1a;“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点&…

新版DAEMON Tools Lite打不开 bin 文件解决方法

DAEMON Tools Lite 支持打开 *.cue 解决方法很简单&#xff1a;将*.bin 重命名为 *.cue 就可以打开

Linux集群架构(LVS DR模式搭建、keepalived + LVS)

为什么80%的码农都做不了架构师&#xff1f;>>> LVS DR模式搭建 准备工作&#xff1a;三台机器 分发器&#xff0c;也叫调度器&#xff08;简写为dir&#xff09;&#xff1a;192.168.248.128 rs1 &#xff1a;192.168.248.129 rs2 : 192.168.248.130 vip : 192.16…

java手机状态栏圆形图标,android实现状态栏添加图标的函数实例

本文实例讲述了android实现状态栏添加图标的函数。分享给大家供大家参考。具体如下&#xff1a;private void showNotification() {// 创建一个NotificationManager的引用NotificationManager notificationManager (NotificationManager)AutoFile.this.getSystemService(andro…

Windows下SVN回滚到旧版本(TortoiseSVN)

原文地址&#xff1a;https://www.cnblogs.com/tommy-huang/p/4729634.html ---------------------------------------- 当发现新提交的代码有问题&#xff0c;然后想将某个旧的版本作为最新的版本时&#xff0c;可以使用回滚&#xff0c; 操作步骤如下&#xff1a; 1. 签出…

看懂架构设计中的服务隔离

前言 我们在做系统架构设计的时候&#xff0c;经常离不开的一个话题就是进行服务的隔离设计。 那什么是「服务隔离」呢&#xff1f; 顾名思义&#xff0c;它是指将系统按照一定的原则划分为若干个服务模块&#xff0c;各个模块之间相对独立&#xff0c;无强依赖。当有故障发生时…

2018最新苹果APP上架App Store流程(超详细)

内容很丰富&#xff0c;点击查看博文 https://blog.csdn.net/xxw888/article/details/73618837/

[五] JavaIO之InputStream OutputStream简介 方法列表说明

InputStream 和 OutputStream 对于字节流的输入和输出 是作为协议的存在 所以有必要了解下这两个类提供出来的基本约定 这两个类是抽象类,而且基本上没什么实现,都是依赖于子类具体的去实现 但是他是对于其子类 协议纲领一般的存在 了解清楚每一个方法含义,对于后续具体的子类将…

Mysql yum 安装后,一些重要的文件路径

默认配置文件路径&#xff1a; 配置文件&#xff1a;/etc/my.cnf 日志文件&#xff1a;/var/log//var/log/mysqld.log 服务启动脚本&#xff1a;/usr/lib/systemd/system/mysqld.service socket文件&#xff1a;/var/run/mysqld/mysqld.pid #(a)数据库目录 /var/lib/mysql…

mysql双机热备 配置文件,MYSQL 双机热备配置手册()

[原创] MYSQL 双机热备配置手册[原创]http://www.chinaunix.net 作者:squall1 发表于&#xff1a;2007-07-23 19:01:43【发表评论】【查看原文】【存储备份之家讨论区】【关闭】作者&#xff1a;CU-squall发表于&#xff1a;2005年4月18日 8:21 可以不经作者同意自由传播&…

[转]资本经营董事长班告诉你:不只企业有商业模式,个人商业价值更重要

本文转自&#xff1a;http://blog.sina.com.cn/s/blog_181b5b47e0102xz4v.html 东方财智-资本经营董事长班>>> 经营者如何轻松驾驭金融工具为企业发展加速、升级互联网工具实现品牌营销裂变、利用管理工具优化公司内部结构&#xff0c;把握前沿视角&#xff0c;实现快…

CentOS 7添加开机启动服务脚本

原文路径&#xff1a;https://blog.csdn.net/wang123459/article/details/79063703 --------------------------------------------------------- 一、添加开机自启服务 在CentOS 7中添加开机自启服务非常方便&#xff0c;只需要两条命令(以Jenkins为例)&#xff1a; system…

php 彩票系统,hsyl12141511 一套完整的PHP版彩票系统 - 下载 - 搜珍网

文件名大小更新时间BOEKJ02017-12-14BOEKJ\.idea02017-12-13BOEKJ\.idea\BOEKJ.iml2812017-04-28BOEKJ\.idea\modules.xml2622017-04-28BOEKJ\.idea\workspace.xml100272017-04-28BOEKJ\String-ext.js10402015-05-30BOEKJ\TianHeng.exe230402015-05-05BOEKJ\config.js309232017…

CPR认证-建材CE认证-305/2011/EU

建材CPR认证 - Regulation (EU) No 305/2011  2011年3月&#xff0c;欧盟颁布了新建筑产品法规RETULATION &#xff08;EU&#xff09; No 305/2011 – CPR&#xff0c;并通告了新法规于2013年7月进入强制执行&#xff0c;取代了老CPD指令89/106/EEC。  新的建材CPR认证也是…

python支持复数类型以下什么说法是错误的,【Python】专项练习题(1)

1.python代码如下:foo [1,2]foo1 foofoo.append(3)A.foo 值为[1,2]B.foo 值为[1,2,3]C.foo1 值为[1,2]D.foo1 值为[1,2,3]答案&#xff1a;B D链接&#xff1a;https://www.nowcoder.com/profile/153165401/myFollowings/detail/20055659来源&#xff1a;牛客网2.下列程序打印…