在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.pswp.cn/news/537905.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/537905.shtml
英文地址,請注明出處:http://en.pswp.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.下列程序打印…