对于我的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
有办法解决这个问题吗?
我想我知道你遇到问题的原因。查看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类型。其他人可能会给你一个更好的解决方案,我会关注的,因为我也很好奇。
只需子类date
即可获得此功能。由于日期时间对象是不可变的,因此需要使用__new__
构造函数与__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类,所以左边的类需要具有正确的比较运算符来处理与右边的类的比较。如果两个类都没有比较运算符,则实例将按标识(它们的内存地址)进行排序。你的错误本质上是试图将苹果与橙子进行比较:将身份与日期类进行比较。
请注意,曾经有一个rcmp在Python 2.1中被删除以处理此类问题。新样式类的引入和丰富的比较也导致__cmp__
被弃用。
找到了一个潜在的解决方案,以防其他人面临同样的问题。
来自Python日期时间文档:
换句话说,date1<date2当且仅当date1.toordinal()<date2.toordinal()。为了防止比较返回到比较对象地址的默认方案,如果另一个comparand不是日期对象,则日期比较通常会引发TypeError但是,如果另一个comparand具有timetuple()属性,则返回NotImplemented。这个钩子为其他类型的日期对象提供了实现混合类型比较的机会如果不是,则当将日期对象与不同类型的对象进行比较时,除非比较为==或!=,否则会引发TypeError。后一种情况分别返回False或True。
如果x.__op__(y)
返回NotImplemented
而不是引发TypeError
,Python将自动尝试反向比较y.__rop__(x)
(此处提供有关比较的更多信息)。
但是,如果另一个对象不是date
对象,则date
将引发TypeError
,除非另一对象实现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