問(wèn)題
你想定義一個(gè)接口或抽象類,并且通過(guò)執(zhí)行類型檢查來(lái)確保子類實(shí)現(xiàn)了某些特定的方法
解決方案
使用 abc
模塊可以很輕松的定義抽象基類:
1
2
3
4
5
6
7
8
9
10
|
from abc import ABCMeta, abstractmethod class IStream(metaclass = ABCMeta): @abstractmethod def read( self , maxbytes = - 1 ): pass @abstractmethod def write( self , data): pass |
抽象類的一個(gè)特點(diǎn)是它不能直接被實(shí)例化,比如你想像下面這樣做是不行的:
1
2
|
a = IStream() # TypeError: Can't instantiate abstract class # IStream with abstract methods read, write |
抽象類的目的就是讓別的類繼承它并實(shí)現(xiàn)特定的抽象方法:
1
2
3
4
5
6
|
class SocketStream(IStream): def read( self , maxbytes = - 1 ): pass def write( self , data): pass |
抽象基類的一個(gè)主要用途是在代碼中檢查某些類是否為特定類型,實(shí)現(xiàn)了特定接口:
1
2
3
4
|
def serialize(obj, stream): if not isinstance (stream, IStream): raise TypeError( 'Expected an IStream' ) pass |
除了繼承這種方式外,還可以通過(guò)注冊(cè)方式來(lái)讓某個(gè)類實(shí)現(xiàn)抽象基類:
1
2
3
4
5
6
7
8
|
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
還能注解靜態(tài)方法、類方法和 properties
。 你只需保證這個(gè)注解緊靠在函數(shù)定義前即可:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
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 |
討論
標(biāo)準(zhǔn)庫(kù)中有很多用到抽象基類的地方。collections
模塊定義了很多跟容器和迭代器(序列、映射、集合等)有關(guān)的抽象基類。 numbers
庫(kù)定義了跟數(shù)字對(duì)象(整數(shù)、浮點(diǎn)數(shù)、有理數(shù)等)有關(guān)的基類。io
庫(kù)定義了很多跟I/O操作相關(guān)的基類。
你可以使用預(yù)定義的抽象類來(lái)執(zhí)行更通用的類型檢查,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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可以讓我們很方便的做類型檢查,但是我們?cè)诖a中最好不要過(guò)多的使用它。 因?yàn)镻ython的本質(zhì)是一門(mén)動(dòng)態(tài)編程語(yǔ)言,其目的就是給你更多靈活性, 強(qiáng)制類型檢查或讓你代碼變得更復(fù)雜,這樣做無(wú)異于舍本求末。
以上就是Python如何定義接口和抽象類的詳細(xì)內(nèi)容,更多關(guān)于Python定義接口和抽象類的資料請(qǐng)關(guān)注服務(wù)器之家其它相關(guān)文章!
原文鏈接:https://python3-cookbook.readthedocs.io/zh_CN/latest/c08/p12_define_interface_or_abstract_base_class.html