#抽象基类是一个分配身份的机制
# 声明虚拟子类 ABCMeta抽象基类的元类
import abc
class AbstractDict(metaclass=abc.ABCMeta):
def foo(self):
return None
ab = AbstractDict.register(dict)
print(ab)
# print(ab.foo())
print(isinstance({},AbstractDict))
print(issubclass(dict,AbstractDict))
# 声明虚拟子类的原因
# 抽象基类可以提供一个非常好的扩展机制,示例如下:
class MySequence(metaclass=abc.ABCMeta):
pass
MySequence.register(list)
MySequence.register(tuple)
print(isinstance([],MySequence))
print(isinstance((),MySequence))
print(isinstance(object(),MySequence))
class CustomListLikeClass(object):
pass
MySequence.register(CustomListLikeClass)
print('object*************************')
print(isinstance(CustomListLikeClass(),MySequence))
#python3.3以来register方法可以作为装饰器,因为register方法返回类,3.3版本之前返回None,因此不能作为装饰器
@MySequence.register
class CustomListLikeClass(object):
pass
class AbstractDuck(metaclass=abc.ABCMeta):
"""该抽象基类声明,任何带有quack方法的类都被认为是他的子类"""
@classmethod
def __subclasshook__(cls,other):
quack = getattr(other,'quack',None)
return callable(quack)
class Duck(object):
def quack(self):
pass
print(issubclass(Duck,AbstractDuck))
class NotDuck(object):
quack = 'foo'
AbstractDuck.register(NotDuck) #当__subclasshook__被定义时,优先级大于register
print(issubclass(NotDuck,AbstractDuck))
# 以上展示抽象基类是如何使一个类能够声明它自身可以通过类型检查测试
# 其他现有方法#######################################################
# 1.使用NotImplementedError
from datetime import datetime
class Task(object):
def __init__(self):
self.runs = []
def run(self):
start = datetime.now()
result = self._run()
end = datetime.now()
self.runs.append({'start':start,
'end':end,
'result':result})
return result
def _run(self):
raise NotImplementedError('Task subclasses must define a _run method')
t = Task()
# t.run()
# 2.使用元类
class TaskMeta(type):
def __new__(cls,name,bases,attrs):
if attrs.pop('abstract',False):
return super(TaskMeta, cls).__new__(cls,name,bases,attrs)
new_class = super(TaskMeta, cls).__new__(cls,name,bases,attrs)
if not hasattr(new_class,'_run') or not callable(new_class._run):
raise TypeError('Task subclass must define _run method')
return new_class
class Task1(metaclass=TaskMeta):
abstract = True
pass
Task1()
# 抽象基类的价值
class Task3(metaclass=abc.ABCMeta):
def __init__(self):
self.runs = []
def run(self):
start = datetime.now()
result = self._run()
end = datetime.now()
self.runs.append({'start':start,
'end':end,
'result':result})
return result
@abc.abstractmethod
def _run(self):
pass
class SubTask(Task3):
pass
# 无法实例化
# SubTask()
class OtherTask(Task3):
def _run(self):
return 2
OtherTask().run()
# 抽象属性
class AbstractClass(metaclass=abc.ABCMeta):
@property
@abc.abstractproperty
def foo(self):
pass
# 抽象类或静态方法
class AbstractClass1(metaclass=abc.ABCMeta):
@classmethod
@abc.abstractmethod
def foo(cls):
return 42
class SubC(AbstractClass1):
pass
print(SubC.foo())
# SubC不能实例化
# 内置抽象基类
from collections.abc import *
Callable(__call__)
Container(__contains__)
Hashable(__hash__)
Iterable(__iter__)
Sized(__len__)