python 抽象基类

#抽象基类是一个分配身份的机制
# 声明虚拟子类 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__)
posted @ 2020-08-04 16:59  ~相忘于江湖  阅读(222)  评论(0)    收藏  举报