python 抽象基類
阿新 • • 發佈:2020-08-04
#抽象基類是一個分配身份的機制
# 宣告虛擬子類 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__)