Python实现抽象基类的3三种方法
来源:互联网 发布:脸部黄金比例测试软件 编辑:程序博客网 时间:2024/06/16 16:32
Python的抽象基类类似于Java、C++等面向对象语言中的接口的概念。抽象基类提供了一种要求子类实现指定协议的方式,如果一个抽象基类要求实现指定的方法,而子类没有实现的话,当试图创建子类或者执行子类代码时会抛出异常。这里简单介绍一下Python实现抽象基类的三种方法。
方法一:使用NotImplementedError
见下面的测试代码,只有子类实现了run方法才能运行run。
>>> class Task(): def __init__(self, x, y): self.x = x self.y = y>>> class Task(): def __init__(self, x, y): self.x = x self.y = y def run(self): raise NotImplementedError('Please define "a run method"')>>> t = Task(1, 2)>>> t.run()Traceback (most recent call last): File "<pyshell#12>", line 1, in <module> t.run() File "<pyshell#10>", line 6, in run raise NotImplementedError('Please define "a run method"')NotImplementedError: Please define "a run method">>>>>> class SubTask(Task): def __init__(self, x, y): super().__init__(x, y) def run(self): print('Task(x=%s, y=%s)' % (self.x, self.y))>>> st = SubTask(1, 3)>>> st.run()Task(x=1, y=3)>>>
方法二:使用元类
class TaskMeta(type): def __new__(cls, name, bases, attrs): new_class = super(TaskMeta, cls).__new__(cls, name, bases, attrs) if attrs.pop('abstract', False): return new_class if not hasattr(new_class, 'run') or not callable(new_class.run): raise TypeError('Please define "a run method"') return new_classclass Task(metaclass=TaskMeta): abstract = True def __init__(self, x, y): self.x = x self.y = yclass SubTask(Task): def __init__(self, x, y): super().__init__(x, y) def run(self): print('Task(x=%s, y=%s)' % (self.x, self.y))
测试代码一:
>>> t = Task(1, 3)>>> t.run()Traceback (most recent call last): File "E:/Code/python3/loggingTest/task.py", line 32, in <module> t.run()AttributeError: 'Task' object has no attribute 'run'>>> st = SubTask(1, 3)>>> st.run()Task(x=1, y=3)
这个示例类似于方法一,但有一些细微的区别。第一个区别就是Task类本身仍然能被实例化,但是不能运行run方法,否则会抛出AttributeError错误。更为重要的区别在于子类。当子类被创建时元类会运行__new__方法,解释器讲不再允许创建没有run方法的子类。
>>> class SubTask(Task):... pass...Traceback (most recent call last): File "E:/Code/python3/loggingTest/task.py", line 31, in <module> class SubTask(Task): File "E:/Code/python3/loggingTest/task.py", line 10, in __new__ raise TypeError('Please define "a run method"')TypeError: Please define "a run method"
方法三:使用@abstractmethod
abc模块提供了一个使用某个抽象基类声明协议的机制,并且子类一定要提供了一个符合该协议的实现。
import abcclass Task(metaclass = abc.ABCMeta): def __init__(self, x, y): self.x = x self.y = y @abc.abstractmethod def run(self): passclass SubTask(Task): def __init(self, x, y): super().__init__(x, y) def run(self): print('Task(x=%s, y=%s)' % (self.x, self.y))class OtherSubTask(Task): def __init(self, x, y): super().__init__(x, y)
和方法一、方法二的示例类似,但略有不同。第一,Task类本身不能被实例化。
>>> t = Task(1, 3)Traceback (most recent call last): File "E:/Code/python3/loggingTest/test.py", line 23, in <module> t = Task(1, 3)TypeError: Can't instantiate abstract class Task with abstract methods run
对于不能正确重写run方法的子类,在错误的情况下它与之前的两个方法的差别也是不同的。方法一中,使用NotImplementedError,最终在run方法被调用时引发NotImplementedError错误。在方法二中,使用了自定义的TaskMeta元类, 当这个抽象类被创建时引发TypeError错误。
当没有实现run方法的子类实例化时会报错,给出的错误信息与实例化Task类时给出的一样,逻辑上完全符合预期。
>>> ot = OtherSubTask(1, 3)Traceback (most recent call last): File "E:/Code/python3/loggingTest/test.py", line 27, in <module> ot = OtherSubTask(1, 3)TypeError: Can't instantiate abstract class OtherSubTask with abstract methods run但是,当你定义了一个重新了run方法的子类时,那么子类就能够被实例化,就能正常工作。
>>> st = SubTask(1, 3)>>> st.run()Task(x=1, y=3)
阅读全文
0 0
- Python实现抽象基类的3三种方法
- python抽象类、抽象方法的实现
- python 抽象方法 抽象类实现
- 实现抽象类内部的抽象方法
- Python 抽象类抽象方法
- 总结python抽象类和抽象方法的写法
- python:抽象超类的实现
- 冒泡排序的三种实现方法-----python
- python 语言实现字符串的拼接(三种方法)
- 用python实现零钱找零的三种方法
- 矩阵的QR分解(三种方法)Python实现
- 翻转链表的三种方法(python实现)
- 抽象类、抽象方法、接口的区别及实现
- Python抽象类与抽象方法
- 抽象类的继承与方法实现
- python三种方法实现字符串拼接
- 三种方法实现PCA算法(Python)
- OpenJDK源码研究笔记(十四):三种经典的设计方法,接口,接口-抽象类-具体实现类,接口-具体实现类
- Java四大权限修饰符
- java开发规范和优化总结
- 由Combination Sum I II 不懂的地方
- ABBYY finereader 12 激活码-破解版-注册机
- Java学习笔记(4)
- Python实现抽象基类的3三种方法
- 第三课作业2:100以内全部素数
- (笔记)数据结构第一讲-基本概念
- IntelliJ IDEA使用教程SVN的集成与使用
- Python3.4.3中使用imageio库png合成gif
- python的elementtree模块处理中文注意事项
- ASP.NET Core 2.0 开源Git HTTP Server
- 解析内部类
- this易错点