我是Python的新手,我想确保我覆盖__eq__并且__hash__正确,以免以后引起痛苦的错误:
(我正在使用Google App Engine.)
class Course(db.Model):
dept_code = db.StringProperty()
number = db.IntegerProperty()
title = db.StringProperty()
raw_pre_reqs = db.StringProperty(multiline=True)
original_description = db.StringProperty()
def getPreReqs(self):
return pickle.loads(str(self.raw_pre_reqs))
def __repr__(self):
title_msg = self.title if self.title else "Untitled"
return "%s %s: %s" % (self.dept_code, self.number, title_msg)
def __attrs(self):
return (self.dept_code, self.number, self.title, self.raw_pre_reqs, self.original_description)
def __eq__(self, other):
return isinstance(other, Course) and self.__attrs() == other.__attrs()
def __hash__(self):
return hash(self.__attrs())
Run Code Online (Sandbox Code Playgroud)
一个稍微复杂的类型:
class DependencyArcTail(db.Model):
''' A list of courses that is a pre-req for something else '''
courses = db.ListProperty(db.Key)
''' a list of heads that reference this one '''
forwardLinks = db.ListProperty(db.Key)
def __repr__(self):
return "DepArcTail %d: courses='%s' forwardLinks='%s'" % (id(self), getReprOfKeys(self.courses), getIdOfKeys(self.forwardLinks))
def __eq__(self, other):
if not isinstance(other, DependencyArcTail):
return False
for this_course in self.courses:
if not (this_course in other.courses):
return False
for other_course in other.courses:
if not (other_course in self.courses):
return False
return True
def __hash__(self):
return hash((tuple(self.courses), tuple(self.forwardLinks)))
Run Code Online (Sandbox Code Playgroud)
一切都很好看?
更新以反映@ Alex的评论
class DependencyArcTail(db.Model):
''' A list of courses that is a pre-req for something else '''
courses = db.ListProperty(db.Key)
''' a list of heads that reference this one '''
forwardLinks = db.ListProperty(db.Key)
def __repr__(self):
return "DepArcTail %d: courses='%s' forwardLinks='%s'" % (id(self), getReprOfKeys(self.courses), getIdOfKeys(self.forwardLinks))
def __eq__(self, other):
return isinstance(other, DependencyArcTail) and set(self.courses) == set(other.courses) and set(self.forwardLinks) == set(other.forwardLinks)
def __hash__(self):
return hash((tuple(self.courses), tuple(self.forwardLinks)))
Run Code Online (Sandbox Code Playgroud)
Ale*_*lli 14
第一个很好.第二个问题有两个原因:
.courses.courses但不同的两个实体.forwardLinks将比较相等但具有不同的哈希值我会通过使等式依赖于课程和前向链接来修复第二个,但两者都改变为集合(因此没有重复),并且对于散列也是如此.即:
def __eq__(self, other):
if not isinstance(other, DependencyArcTail):
return False
return (set(self.courses) == set(other.courses) and
set(self.forwardLinks) == set(other.forwardLinks))
def __hash__(self):
return hash((frozenset(self.courses), frozenset(self.forwardLinks)))
Run Code Online (Sandbox Code Playgroud)
当然,这是假设正向链路是为对象的"实际价值"是至关重要的,否则他们应该从两个被忽略__eq__和__hash__.
编辑:从最多冗余的__hash__调用中移除tuple(并且可能是破坏性的,如@Mark [[tx !!!]]的评论所示); 改变set到frozenset由@Phillips [[TX !!!]在散列,如所建议的评论.