详解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中的zip函数使用示例
Jan 29 Python
Python中获取对象信息的方法
Apr 27 Python
解析Python中while true的使用
Oct 13 Python
tensorflow: variable的值与variable.read_value()的值区别详解
Jul 30 Python
说说如何遍历Python列表的方法示例
Feb 11 Python
pandas分区间,算频率的实例
Jul 04 Python
python基础教程之while循环
Aug 14 Python
关于numpy.where()函数 返回值的解释
Dec 06 Python
Python xlrd excel文件操作代码实例
Mar 10 Python
Python自动化测试笔试面试题精选
Mar 12 Python
keras中的History对象用法
Jun 19 Python
Docker如何部署Python项目的实现详解
Oct 26 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学习笔记之数组篇
2011/06/28 PHP
PHP中文分词的简单实现代码分享
2011/07/17 PHP
php空间不支持socket但支持curl时recaptcha的用法
2011/11/07 PHP
老司机传授Ubuntu下Apache+PHP+MySQL环境搭建攻略
2016/03/20 PHP
PHP实现无限分类的实现方法
2016/11/14 PHP
php及codeigniter使用session-cookie的方法(详解)
2017/04/06 PHP
phpstorm 正则匹配删除空行、注释行(替换注释行为空行)
2018/01/21 PHP
Laravel框架实现多个视图共享相同数据的方法详解
2019/07/09 PHP
[原创]用javascript实现检测指定目录是否存在的方法
2008/01/12 Javascript
Prototype 工具函数 学习
2009/07/23 Javascript
javascript复制对象使用说明
2011/06/28 Javascript
基于dom编程中 动态创建与删除元素的使用
2013/04/17 Javascript
表单类各种类型(文本框)失去焦点效果jquery代码
2013/04/26 Javascript
javascript随机之洗牌算法深入分析
2014/06/07 Javascript
jQuery实现带有动画效果的回到顶部和底部代码
2015/11/04 Javascript
归纳下js面向对象的几种常见写法总结
2016/08/24 Javascript
JavaScript 继承详解(六)
2016/10/11 Javascript
jQuery插件FusionCharts绘制的2D双柱状图效果示例【附demo源码】
2017/05/13 jQuery
Angular 2 ngForm中的ngModel、[ngModel]和[(ngModel)]的写法
2017/06/29 Javascript
微信小程序如何获取openid及用户信息
2018/01/26 Javascript
JS中的BOM应用
2018/02/02 Javascript
Vue2.5通过json文件读取数据的方法
2018/02/27 Javascript
Vue 中使用vue2-highcharts实现top功能的示例
2018/03/05 Javascript
vue实例中data使用return包裹的方法
2018/08/27 Javascript
vue路由 遍历生成复数router-link的例子
2019/10/30 Javascript
[01:02:53]DOTA2上海特级锦标赛主赛事日 - 5 总决赛Liquid VS Secret第二局
2016/03/06 DOTA
DJANGO-ALLAUTH社交用户系统的安装配置
2014/11/18 Python
用Python编写生成树状结构的文件目录的脚本的教程
2015/05/04 Python
python2 与 python3 实现共存的方法
2018/07/12 Python
对Python中一维向量和一维向量转置相乘的方法详解
2019/08/26 Python
python实现坦克大战
2020/04/24 Python
会计实习期自我鉴定
2013/10/06 职场文书
经济学博士求职自荐信范文
2013/11/23 职场文书
个人政治思想总结
2015/03/05 职场文书
2016银行招聘自荐信
2016/01/28 职场文书
《从现在开始》教学反思
2016/02/16 职场文书