Python:这是覆盖eq和hash的好方法吗?

2024-05-23 11:45:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我是Python新手,我想确保我正确地重写了__eq____hash__,以免以后引起痛苦的错误:

(我正在使用谷歌应用引擎。)

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

稍微复杂一点的类型:

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

一切看起来都很好?

更新以反映@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)))

Tags: selfdbreturniftitledefhashpre
1条回答
网友
1楼 · 发布于 2024-05-23 11:45:33

第一个很好。第二个问题有两个原因:

  1. .courses中可能有重复项
  2. 具有相同.courses但不同.forwardLinks的两个实体将比较相等但具有不同散列

我将通过使相等依赖于进程和前向链接来修复第二个链接,但这两个链接都对集合进行了更改(因此没有重复),对于散列也是如此。一、 e.:

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

这当然是假设前向链接对对象的“真实值”至关重要,否则应该从__eq____hash__中省略它们。

编辑:从__hash__调用tuple中删除,这些调用充其量是多余的(而且可能是有害的,正如@Mark[[tx]的注释所建议的那样!!!]]);根据@Phillips[[tx]的注释建议,将哈希中的set更改为frozenset!!!]].

相关问题 更多 >

    热门问题