python抽象基类无法实例化_Python3 抽象基类

本文介绍了Python中抽象基类的概念,作用和使用场景,包括如何定义抽象基类、抽象方法,以及如何通过register方法和__subclasshook__实现类的关联。同时,探讨了接口设计,展示了如何用抽象基类实现接口的归一化设计,强调了抽象基类在代码规范和统一接口中的重要性。
摘要由CSDN通过智能技术生成

抽象基类

抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化。

抽象类与普通类的不同之处在于:抽象类中要有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。

疑问: 已经有了鸭子类型 和多态 ,为什么还要用这个呢?

答: 为了 解决两个事情

使用抽象基类的情况:

1.某些情况下希望判断某个对象的类型

2.强制子类必须全部实现抽象方法

3.用于接口设计

4.规范不同人的代码

Python中并没有提供抽象类与抽象方法,但是提供了内置模块abc和collections.abc来模拟实现抽象类

抽象基类的定义:

由abc.ABCMeta这个元类实现的类就是抽象基类,如

class BaseObj(metaclass=abc.ABCMeta):"""基类"""@abc.abstractmethoddefget(self, value):print(value)

@abc.abstractmethoddefset(self, key, value):print(key, value)classDog(BaseObj):defget(self, value):print(value)returnvaluedefset(self, key, value):passdog=Dog()print(dog.get('fe_cow'))#输出结果:

fe_cow

fe_cow

继承,使Dog类成为BaseObj的子类,不使用继承,可以用下面两种方法。

register方法

定义好的抽象基类通过register方法可以成为别的类的父类。

抽象基类虽然可以成为别的类的父类,但是别的类并不会继承抽象基类的方法和属性

importabc#定义一个抽象基类

class AbstractClass(metaclass=abc.ABCMeta):pass

#定义一个普通类继承自object

classMyClass(object):pass

#把我们定义的抽象基类注册为MyClass的父类

AbstractClass.register(MyClass)

mc=MyClass()print(issubclass(MyClass, AbstractClass)) #输出True

print(isinstance(mc, AbstractClass)) #输出True

#将我们定义的抽象基类注册到系统定义的类

AbstractClass.register(list)print(isinstance([], AbstractClass)) #输出True

__subclasshook__魔法方法

看过上面的例子你们肯定会觉得,给每个类都注册一遍抽象基类太麻烦了,没错Python的开发者也这么觉得,于是__subclasshook__这个方法出现了

几点说明:

该方法定义在抽象基类中

该方法必须定义为类方法

该方法有三个返回值True: 如果测试类被认为是子类

False: 如果测试类不被认为是子类

NotImplemented: 这个后面讲

class AbstractDuck(metaclass=abc.ABCMeta):

@classmethoddef __subclasshook__(cls, subclass):

quack= getattr(subclass, 'quack', None) #取出subclass的 quack 属性,如果不存在则返回 None

ifcallable(quack):returnTruereturnNotImplementedclassDuck(object):defquack(self):pass

classNotDuck(object):

quack= "foo"

print(issubclass(NotDuck, AbstractDuck))

AbstractDuck.register(NotDuck)print(issubclass(NotDuck, AbstractDuck) )print(isinstance(NotDuck,AbstractDuck))print(issubclass(Duck, AbstractDuck))print(isinstance(Duck,AbstractDuck))

结果:

False

True

False

True

False

示例代码中只是检查是不是子类。因为父类中也没有抽象方法,子类也没有实现,所以,isinstance值为false。

collection.abc模块常用的抽象基类:

__all__ = ["Awaitable", "Coroutine","AsyncIterable", "AsyncIterator", "AsyncGenerator","Hashable", "Iterable", "Iterator", "Generator", "Reversible","Sized", "Container", "Callable", "Collection","Set", "MutableSet","Mapping", "MutableMapping","MappingView", "KeysView", "ItemsView", "ValuesView","Sequence", "MutableSequence","ByteString",

]

抽象类与接口

什么是接口

接口可以理解为自己给使用者来调用自己功能方法的入口。

为什么要用接口

(1)可以实现权限控制,比如可以通过接口做一下访问控制,可以允许或者拒绝调用者的一些操作。

(2)降低了使用者的使用难度,使用者只需要知道怎么调用即可,不需要知道里边的具体实现方法。

抽象类特点

1.规定继承类必须具有抽象基类指定的方法

2.抽象基类无法实例化

以上两个特点,主要用于接口设计

importabcclass Interface(metaclass=abc.ABCMeta):#定义接口Interface类来模仿接口的概念,python中没有interface关键字来定义一个接口。

@abc.abstractmethoddef read(self): #定接口函数read

pass@abc.abstractmethoddef write(self): #定义接口函数write

pass

class Txt(Interface): #文本,具体实现read和write

defread(self):print('文本数据的读取方法')defwrite(self):print('文本数据的读取方法')class Sata(Interface): #磁盘,具体实现read和write

defread(self):print('硬盘数据的读取方法')defwrite(self):print('硬盘数据的读取方法')

抽象类与接口

抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而

接口只强调函数属性的相似性。

抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计

接口与归一化设计

归一化让使用者无需关心对象的类是什么,只需要知道这些对象都具备某些功能就可以了,这极大地降低了使用

者的使用难度。

归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合。

定义一个抽象类的目的:就是为了可以规范不同人的代码

使用抽象类注意的问题:

抽象类中可以包含抽象方法,也可以包含具体方法

抽象类中可以有方法,也可以有属性

抽象类不能直接实例化

子类可以不实现所有的抽象方法,这时子类则不能实例化。

import abc

class People(metaclass=abc.ABCMeta):

# 定义一个抽象的方法

@abc.abstractmethod

def eat(self):

pass

#定义一个抽象类的方法

@abc.abstractclassmethod

def drink(cls):

pass

# 定义一个静态抽象方法

@abc.abstractstaticmethod

def work():

pass

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值