1. 抽象基类
了解Java的开发者对接口不会陌生,Java无法进行多继承,所以引入了接口的概念实现多态,而Python则遵守鸭子类型的编程风格,对于鸭子类型这里不做详细解释,有兴趣可以查询以前的博客。既然Python弱化了多继承的难度,为何还要引入抽象基类这个概念 ?与Java接口类似,Python中抽象基类无法进行实例化,强制实例化会抛出异常
from abc import abstractmethod,ABCMeta
class AbstractBaseHandler(metaclass=ABCMeta) :
@abstractmethod
def get(self):
pass
@abstractmethod
def set(self):
pass
abstract = AbstractBaseHandler()
Traceback (most recent call last):
File "D:/WeChatHandler/metaclassHandler.py", line 266, in <module>
abstract = AbstractBaseHandler()
TypeError: Can't instantiate abstract class AbstractBaseHandler with abstract methods get, set
一般来说,抽象基类的作用分为两种:
1. 检查某个类是否存在某种方法
方法作为类中属性,是同样可以被查询以及检查的,Python提供了多种属性检查的内置函数 hasattr 以及 isinstance
class AbstractBaseModel :
def __len__(self) :
pass
model = AbstractBaseModel()
print(hasattr(model,"__len__"))
from collection.abc import Sized
class AbstractBaseModel :
def __len__(self) :
pass
model = AbstractBaseModel()
print(isinstance(model,Sized))
2. 强制子类必须实现某种方法
from abc import ABCMeta,abstractmethod
class CacheBaseHandler(metaclass=ABCMeta) :
@abstractmethod
def get(self):
raise NotImplementedError
@abstractmethod
def set(self):
raise NotImplementedError
1. 子类继承抽象基类未实现抽象方法
class RedisHandler(CacheBaseHandler) :
pass
redis = RedisHandler()
Traceback (most recent call last):
File "D:/WeChatHandler/metaclassHandler.py", line 269, in <module>
redis = RedisHandler()
TypeError: Can't instantiate abstract class RedisHandler with abstract methods get, set
2. 子类继承抽象基类实现抽象方法
class RedisHandler(CacheBaseHandler) :
def get(self):
pass
def set(self):
pass
redis = RedisHandler()
redis.get()
redis.set()
2. isinstance与type的区别
在代码中,我们有时候需要检查对象属于某种类型,其中最常用的就是type类型,其实isinstance也可以检查对象属于某种类型,且两者有着非常大的差异,通常isinstance用于检查继承链。
class A :
pass
class B(A):
pass
class C(B):
pass
c = C()
print(isinstance(c,C)) #True
print(isinstance(c,B)) #True
print(isinstance(c,A)) #True
print(type(c) is C) #True
print(type(c) is B) #False
print(type(c) is A) #False