我使用的是python2.7
考虑以下代码片段(示例是人为设计的):
import datetime
class ScheduleData:
def __init__(self, date):
self.date = date
def __eq__(self, other):
try:
return self.date == other.date
except AttributeError as e:
return self.date == other
def __hash__(self):
return hash(self.date)
schedule_set = set()
schedule_set.add(ScheduleData(datetime.date(2010, 8, 7)))
schedule_set.add(ScheduleData(datetime.date(2010, 8, 8)))
schedule_set.add(ScheduleData(datetime.date(2010, 8, 9)))
print (datetime.date(2010, 8, 8) in schedule_set)
schedule_list = list(schedule_set)
print (datetime.date(2010, 8, 8) in schedule_list)
结果是出乎意料的(至少对我来说):
^{pr2}$在第一种情况下,给定的日期在schedule_set
中找到,因为我已经覆盖了__hash__
和{
根据我的理解,in
运算符将检查集合的哈希和相等性,但对于列表,它将简单地迭代列表中的项并检查相等性。在
那么这里发生了什么?为什么我对列表in
的第二个测试失败?在
是否必须重写其他列表函数?在
@ryanhaing是对的。对于真正奇怪的解决方法,请将此方法添加到类中:
然后程序将打印
True
两次。这其中的原因是,与Python2中比较过于松散的不幸历史有关。timetuple()
解决方法主要在文档的这一部分中解释:datetime
是最早添加到Python中的类型之一,它试图提供不那么令人惊讶的比较行为。但是,直到Python3,它才变得“真正干净”。在问题是,比较调用的是与您所寻找的相反的
__eq__
函数。当您有一个ScheduleData() == datetime.date()
但in
运算符以相反的顺序执行比较,datetime.date() == ScheduleData()
而不是调用您定义的__eq__
,定义的__eq__
就可以工作了。只有充当左侧的类才会调用其__eq__
。在这个问题出现在python2而不是3中的原因与std库中
datetime.date.__eq__
的定义有关。以以下两类为例:运行此代码将在Python2和Python3下打印
^{pr2}$B.__eq__
。B
对象用作lhs,就像您的datetime.date
对象在python2中使用一样。但是,如果我重新定义B.__eq__
以类似于python3对datetime.date.__eq__
的定义:然后:
在Python 2和Python 3下打印。返回
NotImplemented
会导致参数颠倒的检查。在在你的类中使用
timetuple
可以解决这个问题,正如@TimPeters所说(有趣的怪癖我不知道),尽管它似乎不需要是一个函数是你所需要的,除了你已经拥有的。在
相关问题 更多 >
编程相关推荐