問題
你想定義一個接口或抽象類,并且通過執行類型檢查來確保子類實現了某些特定的方法
解決方案
使用 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 |
抽象類的一個特點是它不能直接被實例化,比如你想像下面這樣做是不行的:
1
2
|
a = IStream() # TypeError: Can't instantiate abstract class # IStream with abstract methods read, write |
抽象類的目的就是讓別的類繼承它并實現特定的抽象方法:
1
2
3
4
5
6
|
class SocketStream(IStream): def read( self , maxbytes = - 1 ): pass def write( self , data): pass |
抽象基類的一個主要用途是在代碼中檢查某些類是否為特定類型,實現了特定接口:
1
2
3
4
|
def serialize(obj, stream): if not isinstance (stream, IStream): raise TypeError( 'Expected an IStream' ) pass |
除了繼承這種方式外,還可以通過注冊方式來讓某個類實現抽象基類:
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
還能注解靜態方法、類方法和 properties
。 你只需保證這個注解緊靠在函數定義前即可:
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 |
討論
標準庫中有很多用到抽象基類的地方。collections
模塊定義了很多跟容器和迭代器(序列、映射、集合等)有關的抽象基類。 numbers
庫定義了跟數字對象(整數、浮點數、有理數等)有關的基類。io
庫定義了很多跟I/O操作相關的基類。
你可以使用預定義的抽象類來執行更通用的類型檢查,例如:
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可以讓我們很方便的做類型檢查,但是我們在代碼中最好不要過多的使用它。 因為Python的本質是一門動態編程語言,其目的就是給你更多靈活性, 強制類型檢查或讓你代碼變得更復雜,這樣做無異于舍本求末。
以上就是Python如何定義接口和抽象類的詳細內容,更多關于Python定義接口和抽象類的資料請關注服務器之家其它相關文章!
原文鏈接:https://python3-cookbook.readthedocs.io/zh_CN/latest/c08/p12_define_interface_or_abstract_base_class.html