它是什么?

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

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

1
2
3
4
5
6
7
8
>>> 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:

1
2
>>> bool(NotImplemented)
True

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 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

现在,在解释器中:

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

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

1
2
3
>>> a1 == a1
Comparing an A with an A
True

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

1
2
3
>>> b1 == b1
Comparing a B with another B
True

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

1
2
3
>>> a1 == b1
Comparing an A with a B
True

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

1
2
3
4
>>> 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中内置的NotImplemented类型的用法的更多相关文章

  1. Python中内置的日志模块logging用法详解

    logging模块简介 Python的logging模块提供了通用的日志系统,可以方便第三方模块或者是应用使用.这个模块提供不同的日志级别,并可以采用不同的方式记录日志,比如文件,HTTP GET/P ...

  2. 详解Python中re.sub--转载

    [背景] Python中的正则表达式方面的功能,很强大. 其中就包括re.sub,实现正则的替换. 功能很强大,所以导致用法稍微有点复杂. 所以当遇到稍微复杂的用法时候,就容易犯错. 所以此处,总结一 ...

  3. 举例详解Python中的split()函数的使用方法

    这篇文章主要介绍了举例详解Python中的split()函数的使用方法,split()函数的使用是Python学习当中的基础知识,通常用于将字符串切片并转换为列表,需要的朋友可以参考下   函数:sp ...

  4. 小白基础Python重要的字符串详解String的内置方法

    String的内置方法: st='hello world  {name} is {age}'  {}  特殊内容需要识别format print(st.count('1')) 统计元素个数 print ...

  5. 详解Python中的循环语句的用法

    一.简介 Python的条件和循环语句,决定了程序的控制流程,体现结构的多样性.须重要理解,if.while.for以及与它们相搭配的 else. elif.break.continue和pass语句 ...

  6. 详解 Python 中的下划线命名规则

    在 python 中,下划线命名规则往往令初学者相当 疑惑:单下划线.双下划线.双下划线还分前后……那它们的作用与使用场景 到底有何区别呢?今天 就来聊聊这个话题. 1.单下划线(_) 通常情况下,单 ...

  7. 详解python中@的用法

    python中@的用法 @是一个装饰器,针对函数,起调用传参的作用. 有修饰和被修饰的区别,‘@function'作为一个装饰器,用来修饰紧跟着的函数(可以是另一个装饰器,也可以是函数定义). 代码1 ...

  8. 详解python中的生成器表达式

    什么是生成器表达式 还记得列表解析吗?我们把[]换成()就变成生成器表达式了. g = (x for x in [1, 2, 3, 4]) print(g) # <generator objec ...

  9. 详解python中的描述符

    描述符介绍 总所周知,python声明变量的时候,不需要指定类型.虽然现在有了注解,但这只是一个规范,在语法层面是无效的.比如: 这里我们定义了一个hello函数,我们要求name参数传入str类型的 ...

随机推荐

  1. birt运行环境

    1.下载 http://pan.baidu.com/s/1nvhz5wt 2.解压birt-runtime-4.6.0-20160607.zip 将WebViewerExample更名为birt,复制 ...

  2. easyui combobox下拉框中显示大于号小于号的问题

    前两天同事做了个功能,通过勾选下拉框里的值进行列表查询,结果下拉框里的值是“0<t<=2”.“2<t<=5”.“t>5”这样的. combobox是用脚本渲染出来的,里面 ...

  3. Centos无法连接无线网络解决办法

    系统->管理->服务器设置->服务,将NetworkManager选项勾选,点击重启服务.然后就可以看到右上角已经有了网络连接.

  4. Struts_登录练习(配置拦截器)

    需求:类似过滤器看有没有登录,没登陆就返回登陆界面,在上文基础上实现 1.新建拦截器 2.配置拦截器 3.完成.

  5. 模拟3题解 T3建造游乐园

    T3建造游乐园 这题的关键是推式子 i个点中,有g[i]个方案是度为偶数但不一定连通那么就要减去不合法的设已有j个合法,其个数为f[j],剩下i-j个的方案数是g[i-j]选出来一个固定的点在合法的j ...

  6. bzoj 1045 [HAOI2008] 糖果传递——设变量推式子

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1045 费用流TLE. #include<iostream> #include&l ...

  7. Android消息机制使用注意事项,防止泄漏

    在Android的线程通信当中,使用频率最多的就是Android的消息处理机制(Handler.send().View.post().Asynctask.excute()等等都使用到了消息处理机制). ...

  8. ELK之java虚拟机安装1

    建议:直接按照默认路径,下面有一个路径我有点小改动 java最新版本1.12 从官网上下载oracle官网上的jdk 1.双击这个jdk.exe 2.点击"是" 3.点击下图的&q ...

  9. day39-Spring 02-AOP的概述

     横向抽取的机制其实就是代理机制.对UserDao生成一个代理类:UserDaoProxy.被代理对象和代理对象它俩实现相同的接口它俩肯定是平级的,这就是横向抽取的机制.如果这时候调用UserDao的 ...

  10. TCPThree_C杯 Day1

    题解 或 正规题解 已经很详细,不再赘述. 跟着wjx打代码,不怕卡题. 忘开long long智障错误第四次左偏树