详解Python中内置的NotImplemented类型的用法


Posted in Python onMarch 31, 2015

它是什么?
 

>>> type(NotImplemented)
<type 'NotImplementedType'>

NotImplemented 是Python在内置命名空间中的六个常数之一。其他有False、True、None、Ellipsis 和 __debug__。和 Ellipsis很像,NotImplemented 能被重新赋值(覆盖)。对它赋值,甚至改变属性名称, 不会产生 SyntaxError。所以它不是一个真正的“真”常数。当然,我们应该永远不改变它。 但是为了完整性:
 

>>> None = 'hello'
...
SyntaxError: can't assign to keyword
>>> NotImplemented
NotImplemented
>>> NotImplemented = 'do not'
>>> NotImplemented
'do not'

它有什么用?什么时候用?

NotImplemented 是个特殊值,它能被二元特殊方法返回(比如__eq__() 、 __lt__()  、 __add__() 、 __rsub__() 等),表明某个类型没有像其他类型那样实现这些操作。同样,它或许会被原地处理(in place)的二元特殊方法返回(比如__imul__()、__iand__()等)。还有,它的实际值为True:
 

>>> bool(NotImplemented)
True

你也许会问自己,“但我认为当这个操作没有实现时,我应该产生个NotImpementedError”。我们会看些例子,关于为什么当实现二元特殊方法时不是这么回事儿。

让我们看看NotImplemented常数的用法,通过__eq__()对于两个非常基本(且没用)的类 A 和 B 的编码。[对于这个简单的例子,为了避免干扰,不会实现__ne__() ,但是总的说来,每次实现__eq__() 时, __ne__()也应该被实现,除非,有个足够充分的理由去不实现它。]
 

# example.py
 
class A(object):
  def __init__(self, value):
    self.value = value
 
  def __eq__(self, other):
    if isinstance(other, A):
      print('Comparing an A with an A')
      return other.value == self.value
    if isinstance(other, B):
      print('Comparing an A with a B')
      return other.value == self.value
    print('Could not compare A with the other class')
    return NotImplemented
 
class B(object):
  def __init__(self, value):
    self.value = value
 
  def __eq__(self, other):
    if isinstance(other, B):
      print('Comparing a B with another B')
      return other.value == self.value
    print('Could not compare B with the other class')
    return NotImplemented

现在,在解释器中:
 

>>> from example import A, B
>>> a1 = A(1)
>>> b1 = B(1)

我们现在可以实验下对于 __eq__() 不同的调用,看看发生了什么。作为提醒,在Python中,a == b会调用a.__eq__(b):
 

>>> a1 == a1
Comparing an A with an A
True

正如所望,a1等于a1(自己),使用类A中的__eq__()来进行这个比较的。比较b1和它自己也会产生类似结果:
 

>>> b1 == b1
Comparing a B with another B
True

现在,那要是我们比较a1和b1呢?由于在A的__eq__()会检查other是不是B的一个实例,我们想要a1.__eq__(b1)去处理这个比较并返回True:
 

>>> a1 == b1
Comparing an A with a B
True

就是这样。现在,如果我们比较b1和a1(即调用b1.__eq__(a1)),我们会想要返回NotImplemented。这是因为B的__eq__()只和其他B的实例进行比较。来看看发生了什么:
 

>>> b1 == a1
Could not compare B against the other class
Comparing an A with a B
True

聪明!b1.__eq__(a1)方法返回NotImplemented,这样会导致调用A中的__eq__()方法。而且由于在A中的__eq__()定义了A和B之间的比较,所以就得到了正确的结果(True)。

这就是返回了NotImplemented的所做的。NotImplemented告诉运行时,应该让其他对象来完成某个操作。在表达b1 == a1中,b1.__eq__(a1)返回了NotImplemented,这说明Python试着用a1.__eq__(b1)。由于a1足够可以返回True,因此这个表达可以成功。如果A中的__eq__()也返回NotImplemented,那么运行时会退化到使用内置的比较行为,即比较对象的标识符(在CPython中,是对象在内存中的地址)。

注意:如果在调用b1.__eq__(a1)时抛出NotImpementedError,而不进行处理,就会中断代码的执行。而NotImplemented无法抛出,仅仅是用来进一步测试是否有其他方法可供调用。

Python 相关文章推荐
利用Python实现图书超期提醒
Aug 02 Python
Python iter()函数用法实例分析
Mar 17 Python
pandas 对每一列数据进行标准化的方法
Jun 09 Python
python进行两个表格对比的方法
Jun 27 Python
查找python项目依赖并生成requirements.txt的方法
Jul 10 Python
Python使用sax模块解析XML文件示例
Apr 04 Python
基于python3监控服务器状态进行邮件报警
Oct 19 Python
python中dict()的高级用法实现
Nov 13 Python
python 使用cx-freeze打包程序的实现
Mar 14 Python
Python socket服务常用操作代码实例
Jun 22 Python
python打包生成so文件的实现
Oct 30 Python
Python 使用xlwt模块将多行多列数据循环写入excel文档的操作
Nov 10 Python
python计算N天之后日期的方法
Mar 31 #Python
使用Python3中的gettext模块翻译Python源码以支持多语言
Mar 31 #Python
python根据出生日期获得年龄的方法
Mar 31 #Python
用Python进行一些简单的自然语言处理的教程
Mar 31 #Python
用Python制作在地图上模拟瘟疫扩散的Gif图
Mar 31 #Python
以一段代码为实例快速入门Python2.7
Mar 31 #Python
11个并不被常用但对开发非常有帮助的Python库
Mar 31 #Python
You might like
php入门学习知识点八 PHP中for循环基本应用之九九乘法口绝表
2011/07/14 PHP
php实现执行某一操作时弹出确认、取消对话框
2013/12/30 PHP
php格式化json函数示例代码
2016/05/12 PHP
TP3.2框架分页相关实现方法分析
2020/06/03 PHP
extjs grid设置某列背景颜色和字体颜色的方法
2010/09/03 Javascript
Jquery公告滚动+AJAX后台得到数据
2011/04/14 Javascript
怎样在JavaScript里写一个swing把数据插入数据库
2012/12/10 Javascript
JS组件Bootstrap Table表格行拖拽效果实现代码
2020/08/27 Javascript
js 获取当前web应用的上下文路径实现方法
2016/08/19 Javascript
JS控制TreeView的结点选择
2016/11/11 Javascript
轻松学习Javascript闭包
2017/03/01 Javascript
Vue.directive 自定义指令的问题小结
2018/03/04 Javascript
用Node提供静态文件服务的方法
2018/07/06 Javascript
Layui数据表格之获取表格中所有的数据方法
2018/08/20 Javascript
vue将毫秒数转化为正常日期格式的实例
2018/09/16 Javascript
使用pkg打包Node.js应用的方法步骤
2018/10/19 Javascript
NodeJs操作MongoDB教程之分页功能以及常见问题
2019/04/09 NodeJs
vue指令之表单控件绑定v-model v-model与v-bind结合使用
2019/04/17 Javascript
Python中文编码那些事
2014/06/25 Python
python多重继承新算法C3介绍
2014/09/28 Python
Python基础语言学习笔记总结(精华)
2017/11/14 Python
教你利用Python玩转histogram直方图的五种方法
2018/07/30 Python
libreoffice python 操作word及excel文档的方法
2019/07/04 Python
python requests库爬取豆瓣电视剧数据并保存到本地详解
2019/08/10 Python
Python中logging日志库实例详解
2020/02/19 Python
python实现猜数游戏
2020/03/27 Python
关于Python3的import问题(pycharm可以运行命令行import错误)
2020/11/18 Python
amaze ui 的使用详细教程
2020/08/19 HTML / CSS
世界第一冲浪品牌:O’Neill
2016/08/30 全球购物
奇怪的鱼:Weird Fish
2018/03/18 全球购物
CHARLES & KEITH台湾官网:新加坡时尚品牌
2019/07/30 全球购物
怎样在程序里获得一个空指针
2015/01/24 面试题
经典c++面试题六
2012/01/18 面试题
三八节标语
2014/06/27 职场文书
学习计划是什么
2019/04/30 职场文书
Java方法重载和方法重写的区别到底在哪?
2021/06/11 Java/Android