今天寫代碼時無意碰到NotImplemented,我一愣,難道是NotImplementedError的胞弟,所以稍微研究了一下。
NotImplemented故名思議,就是“未實現”,一般是用在一些比較算法中的,如class的__eq__,__lt__等,注意NotImplemented並不是異常,所以不能
使用raise,當沒有實現時應該是return NotImplemented。
我們可以看看django中的Field的實現,
@total_ordering
class Field(object):
"""Base class for all field types"""
def __eq__(self, other):
# Needed for @total_ordering
if isinstance(other, Field):
return self.creation_counter == other.creation_counter
return NotImplemented
def __lt__(self, other):
# This is needed because bisect does not take a comparison function.
if isinstance(other, Field):
return self.creation_counter < other.creation_counter
return NotImplemented
那提供NotImplemented有什麼好處?好處就在於如果A == B NotImplemented,會去調用B的__eq__方法,如果B也沒有會調用cmp方法。
我們看下面一個例子:
class Person:
def __init__(self, age):
self.age = age
def __eq__(self, other):
if not isinstance(other, Person):
return NotImplemented
return self.age == other.age
如果你們穩定庫中有這麼一段代碼,而且Person可能包含了很多字段,但是你想實現Person和整數比較。
person=Person(10)
print person == 10 #False
很遺憾,上面結果是False,不符合我們要求,至於爲什麼是10,稍後再說,我們先看看如何解決這個問題?其實這時你可以簡單封裝一個age對象,
class Age:
def __init__(self, age):
self.age = age
def __eq__(self, other):
return self.age == other.age
person=Person(10)
age=Age(10)
print person == age #True
ok,很完美,那我們從上面能得到什麼結論呢?我們在寫一些基礎代碼時,即使是沒實現,也不要raise NotImplementedError,而是return NotImplemented,相當於提供給其它不同對象的比較接口,這對
代碼擴展非常有好處。
我們再來看看上面那麼直接和10比,爲什麼是False?
先看下面這段代碼:
class A:
def __lt__(self, a):
return NotImplemented
def __add__(self ,a):
return NotImplemented
print A() < A() # True
print A() < 1 # False
很奇怪吧,明明已經直接是NotImplemented,爲什麼還有結果?大膽猜測,前面說明最後會使用cmp比較,很明顯當都沒有定義時會比較id值,也就是內存地址,後創建的對象內存地址大,就是這個道理。
至於A() < 1,因爲python的小整數對象在初始化時創建的,內存地址肯定小,如果你還不信,
不過千萬別搞沒有意思的操作,
這也是這位兄弟不解的地方,http://stackoverflow.com/questions/1062096/python-notimplemented-constant