8.12 定义接�或者抽象基类¶
问题¶
ä½ æƒ³å®šä¹‰ä¸€ä¸ªæŽ¥å�£æˆ–抽象类,并且通过执行类型检查æ�¥ç¡®ä¿�å�类实现了æŸ�些特定的方法
解决方案¶
使用 abc 模��以很轻�的定义抽象基类:
from abc import ABCMeta, abstractmethod
class IStream(metaclass=ABCMeta):
@abstractmethod
def read(self, maxbytes=-1):
pass
@abstractmethod
def write(self, data):
pass
抽象类的一个特点是它ä¸�èƒ½ç›´æŽ¥è¢«å®žä¾‹åŒ–ï¼Œæ¯”å¦‚ä½ æƒ³åƒ�下é�¢è¿™æ ·å�šæ˜¯ä¸�行的:
a = IStream() # TypeError: Can't instantiate abstract class
# IStream with abstract methods read, write
抽象类的目的就是让别的类继承它并实现特定的抽象方法:
class SocketStream(IStream):
def read(self, maxbytes=-1):
pass
def write(self, data):
pass
抽象基类的一个主è¦�用途是在代ç �䏿£€æŸ¥æŸ�些类是å�¦ä¸ºç‰¹å®šç±»åž‹ï¼Œå®žçŽ°äº†ç‰¹å®šæŽ¥å�£ï¼š
def serialize(obj, stream):
if not isinstance(stream, IStream):
raise TypeError('Expected an IStream')
pass
除了继承这�方�外,还�以通过注册方��让�个类实现抽象基类:
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 。
ä½ å�ªéœ€ä¿�è¯�这个注解紧é� 在函数定义å‰�å�³å�¯ï¼š
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æ“�作相关的基类。
ä½ å�¯ä»¥ä½¿ç”¨é¢„定义的抽象类æ�¥æ‰§è¡Œæ›´é€šç”¨çš„类型检查,例如:
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的本质是一门动æ€�编程è¯è¨€ï¼Œå…¶ç›®çš„å°±æ˜¯ç»™ä½ æ›´å¤šç�µæ´»æ€§ï¼Œ å¼ºåˆ¶ç±»åž‹æ£€æŸ¥æˆ–è®©ä½ ä»£ç �å�˜å¾—æ›´å¤�æ�‚ï¼Œè¿™æ ·å�šæ— å¼‚äºŽèˆ�本求末。