2013-02-09 69 views
2

對於我的Python 2.7.3項目,我有一個名爲custom_date類,它有一個名爲fixed_date屬性:Python的比較運算符重載

from datetime import date 
class custom_date(): 
    def __init__(self, fixed_date): 
     self.fixed_date = fixed_date 

    def __lt__(self, other): 
     return self.fixed_date < other 

    #__gt__, __ge__, __le__, __eq__, __ne__ all implemented the same way 

我的想法是能夠直接比較custom_date.fixed_date與內置date

問題

如果我比較一個custom_date對象到date對象,它的罰款。但是,如果我比較一date對象到custom_date,它返回一個TypeError

>>> from datetime import date 
>>> x = custom_date(date(2013,2,1)) 
>>> y = date(2013,2,2) 
>>> x > y 
False 
>>> y > x 
TypeError: can't compare datetime.date to instance 

有沒有解決這個辦法嗎?

回答

3

只是子類date得到這個功能。由於DateTime對象是不可改變的,你需要使用__new__構造VS __init__

from datetime import date 
class custom_date(date): 
    def __new__(cls, year,month,day): 
     return date.__new__(cls, year, month,day) 

x = custom_date(2013,2,1) 
y = date(2013,2,2) 

print x<y 
print y<x 

打印:

True 
False 

因爲對於比較決定性類是LH class,左邊的類需要有正確的比較運算符來處理與右邊課程的比較。如果兩個類中都沒有比較運算符,則實例按身份排序 - 它們的內存地址。您的錯誤基本上來自嘗試將蘋果與橙色:身份與日期類別進行比較。

請注意,Python 2.1中曾經有一個rcmpthat was removed來處理這些問題。導致the new style classesrich comparisons也導致__cmp__被棄用。

+0

好的答案,但OP自己的答案是'正確'(和更簡單)的解決方案,因爲它不會強迫你不必要地約束日期。 – Graeme 2015-11-16 21:01:49

3

我想我知道你爲什麼會遇到問題。檢查docs.python.org上的data model documentation

>>> y > x 

電話:

y.__gt__(x) 

x只是一個實例對象,而不是存儲在其中的fixed_date屬性:

>>> x 
<__main__.custom_date instance at 0x020D78C8> 
>>> x.fixed_date 
datetime.date(2012, 2, 1) 

的一種方式,使其工作的方式,你有它設置up up is do:

>>> y > x.fixed_date 

我認爲要「解決」這個問題,你應該讓所有的日期類型爲custom_date。其他人可能會爲你提供更好的解決方案,我也會關注,因爲我也很好奇。

+0

感謝您的信息。我希望能有辦法做'反映'比較,比如'__radd__'和'__add__'。似乎比較運算符是不可能的。 – 2013-02-09 05:25:43

2

找到一個潛在的解決方案,以防其他人面臨同樣的問題。

Python datetime docs

換句話說,DATE1 < DATE2當且僅當date1.toordinal()< date2.toordinal()。爲了停止比較,以回落到比較對象地址的默認方案,如果另一個比較不是日期對象,則日期比較通常會引發TypeError。 但是,如果另一個比較具有timetuple()屬性,則會返回NotImplemented。這個鉤子爲其他類型的日期對象提供了一個實現混合類型比較的機會。如果沒有,則將日期對象與不同類型的對象進行比較時,會引發TypeError,除非比較結果爲==或!=。後者分別返回False或True。

如果x.__op__(y)回報NotImplemented,而不是養TypeError,巨蟒將自動嘗試反向比較y.__rop__(x)(約合比較更多信息here)。然而

date提出了TypeError如果其他對象不是date對象,除非其他對象實現()屬性的timetuple。

所以解決辦法是給我的班級添加一個虛擬的timetuple()方法。

from datetime import date 
class custom_date(): 
    def __init__(self, fixed_date): 
     self.fixed_date = fixed_date 

    def __lt__(self, other): 
     return self.fixed_date < other 

    #__gt__, __ge__, __le__, __eq__, __ne__ all implemented the same way 

    def timetuple(): 
     pass 
+0

哇!好的,學到了新東西。 – dawg 2013-02-10 06:58:22

+0

我認爲你應該接受@ dawg的回答並接受它! – Graeme 2015-11-16 20:59:24