Python比较运算符重载

时间:2013-02-09 04:27:09

标签: python datetime comparison operator-overloading

对于我的Python 2.7.3项目,我有一个名为custom_date的类,它有一个名为fixed_date的属性:

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 个答案:

答案 0 :(得分: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)

使其按照设置方式运行的一种方法是:

>>> y > x.fixed_date

我认为要“解决”这个问题,您可以将所有日期设为custom_date。别人可能会为你提供更好的解决方案,我会留意,因为我也很好奇。

答案 1 :(得分: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中曾经有一个 rcmp that was removed来处理这些问题。 the new style classesrich comparisons的介绍也导致__cmp__被弃用。

答案 2 :(得分:2)

找到一个潜在的解决方案,以防其他人遇到同样的问题。

来自Python datetime docs

  
    

换句话说,date1&lt; date2当且仅当date1.toordinal()&lt; date2.toordinal()。为了阻止比较回退到比较对象地址的默认方案,如果另一个比较不是日期对象,则日期比较通常会引发TypeError。 但是,如果另一个comparand具有timetuple()属性,则返回NotImplemented。此钩子为其他类型的日期对象提供了实现混合类型比较的机会。如果不是,当将日期对象与不同类型的对象进行比较时,除非比较为==或!=,否则引发TypeError 。后一种情况分别返回False或True。

  

如果x.__op__(y)返回NotImplemented而非提出TypeError,则Python会自动尝试反向比较y.__rop__(x)(有关比较here的详细信息)。

date但是如果另一个对象不是TypeError对象,则引发date ,除非另一个对象实现timetuple()属性。< / p>

因此,解决方案是在我的班级中添加一个虚拟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