2

对于我的 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对象与 a进行比较custom_date,它会返回 aTypeError

>>> 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 

有没有办法解决?

4

3 回答 3

3

我想我知道你为什么会遇到问题。检查 docs.python.org 上的数据模型文档

>>> 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 类型。其他人可能对你有更好的解决方案,我会关注的,因为我也很好奇。

于 2013-02-09T05:07:27.640 回答
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 类,所以左边的类需要有正确的比较运算符来处理与右边的类的比较。如果任何一个类都没有比较运算符,则实例按标识排序——它们的内存地址。您的错误本质上是试图将苹果与橙子进行比较:身份与日期类。

请注意,曾经在 Python 2.1中删除了一个rcmp 来处理此类问题。新样式类的引入和丰富的比较也导致被弃用。__cmp__

于 2013-02-09T06:15:21.033 回答
2

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

来自Python 日期时间文档

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

如果x.__op__(y)返回NotImplemented而不是提高 a TypeError,Python 将自动尝试反向比较y.__rop__(x)(有关比较的更多信息here)。

dateTypeError然而,如果另一个对象不是date对象,则引发 a ,除非另一个对象实现 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
于 2013-02-10T03:46:41.527 回答