Python之美[从菜鸟到高手]--NotImplemented小析

今天写代码时无意碰到NotImplemented,我一愣,难道是NotImplementedError的胞弟,所以稍微研究了一下。

NotImplemented故名思议,就是“未实现”,一般是用在一些比较算法中的,如class的__eq__,__lt__等,注意NotImplemented并不是异常,所以不能

使用raise,当没有实现时应该是return NotImplemented。

我们可以看看django中的Field的实现,

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @total_ordering  
  2. class Field(object):  
  3.     """Base class for all field types"""  
  4.     def __eq__(self, other):  
  5.         # Needed for @total_ordering  
  6.         if isinstance(other, Field):  
  7.             return self.creation_counter == other.creation_counter  
  8.         return NotImplemented  
  9.   
  10.     def __lt__(self, other):  
  11.         # This is needed because bisect does not take a comparison function.  
  12.         if isinstance(other, Field):  
  13.             return self.creation_counter < other.creation_counter  
  14.         return NotImplemented  

那提供NotImplemented有什么好处?好处就在于如果A == B NotImplemented,会去调用B的__eq__方法,如果B也没有会调用cmp方法。

我们看下面一个例子:

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. class Person:  
  2.     def __init__(self, age):  
  3.         self.age = age  
  4.   
  5.     def __eq__(self, other):  
  6.         if not isinstance(other, Person):  
  7.             return NotImplemented  
  8.         return self.age == other.age  

如果你们稳定库中有这么一段代码,而且Person可能包含了很多字段,但是你想实现Person和整数比较。

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. person=Person(10)  
  2. print person == 10 #False  
很遗憾,上面结果是False,不符合我们要求,至于为什么是10,稍后再说,我们先看看如何解决这个问题?

其实这时你可以简单封装一个age对象,

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. class Age:  
  2.     def __init__(self, age):  
  3.         self.age = age  
  4.   
  5.     def __eq__(self, other):  
  6.         return self.age == other.age   
  7.   
  8. person=Person(10)  
  9. age=Age(10)  
  10. print person == age #True  
ok,很完美,那我们从上面能得到什么结论呢?

我们在写一些基础代码时,即使是没实现,也不要raise NotImplementedError,而是return NotImplemented,相当于提供给其它不同对象的比较接口,这对

代码扩展非常有好处。


我们再来看看上面那么直接和10比,为什么是False?

先看下面这段代码:

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. class A:  
  2.     def __lt__(self, a):  
  3.         return NotImplemented  
  4.   
  5.     def __add__(self ,a):  
  6.         return NotImplemented  
  7.   
  8. print A() < A() # True  
  9. print A() < 1  # False  
很奇怪吧,明明已经直接是 NotImplemented,为什么还有结果?
大胆猜测,前面说明最后会使用cmp比较,很明显当都没有定义时会比较id值,也就是内存地址,后创建的对象内存地址大,就是这个道理。

至于A() < 1,因为Python的小整数对象在初始化时创建的,内存地址肯定小,如果你还不信,


不过千万别搞没有意思的操作,


这也是这位兄弟不解的地方,http://stackoverflow.com/questions/1062096/python-notimplemented-constant

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值