首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >自动使类成为hashable类

自动使类成为hashable类
EN

Stack Overflow用户
提问于 2012-09-20 20:24:30
回答 2查看 3.3K关注 0票数 4

例如,有几种标准方法可以使类成为可散列的(从SO借用):

代码语言:javascript
复制
# assume X has 2 attributes: attr_a and attr_b
class X:
  def __key(self):
    return (self.attr_a, self.attr_b)

  def __eq__(x, y):
    return isinstance(y, x.__class__) and x.__key() == y.__key()

  def __hash__(self):
    return hash(self.__key())

现在假设我有很多想要hashable的类。它们都是不可变的,具有不可变的属性,批量散列所有这些属性是可以接受的(对于拥有太多属性的类,我们只需要散列一些足以避免大多数冲突的属性)。我可以避免为每个类手工编写__key()方法吗?

创建一个为它们定义__key()__eq____hash__的基类是不是一个好主意?特别是,我不确定是否可以找到应该放入__hash__中的所有实例属性。我知道这是generally impossible,但在这种情况下,我们可以更多地假设对象是不可变的(例如,它是不可变的--在__init__完成后,它的属性都是可散列的,等等)。

(如果继承层次结构不起作用,也许装饰器会起作用?)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-09-20 20:30:27

实例将其属性存储在self.__dict__

代码语言:javascript
复制
>>> class Foo(object):
...     def __init__(self, foo='bar', spam='eggs'):
...         self.foo = foo
...         self.spam = spam
... 
>>> f = Foo()
>>> f.__dict__
{'foo': 'bar', 'spam': 'eggs'}

如果你没有在你的实例上存储任何方法,默认的.__key()可能是:

代码语言:javascript
复制
def __key(self):
    return tuple(v for k, v in sorted(self.__dict__.items()))

其中我们按属性名对项进行排序;tuple()调用确保返回适合于hash()调用的不可变序列。

对于更复杂的设置,您必须测试values()返回的类型(跳过函数等),或者使用特定的属性模式,或者重新调整__slots__的用途以列出您可以使用的适当属性。

再加上__hash____eq__方法,这将成为继承所有不可变类的一个很好的基类。

票数 4
EN

Stack Overflow用户

发布于 2012-09-20 20:31:13

如果你假设你的属性有约定,你可以做到这一点。在您的示例中,这将是非常简单的,因为您的属性以"attr_“开头-所以您可以将您的__key方法编写为:

代码语言:javascript
复制
def __key(self):
    return tuple (getattr(self, attr) for attr in self.__dict__ if attr.startswith("attr_") )

正如你所看到的--你能找到的任何对生成器表达式过滤条件的测试都能满足你的需求。

我可以给你一个建议,让你的类使用Python的__slots__特性:这不仅会让你的属性名更容易找到,还会让你的imutable对象更高效地使用,并且占用更少的内存。

代码语言:javascript
复制
class X:
    __slots__ = ("a", "b", "c")
    def __key(self):
        return tuple (getattr(self, attr) for attr in self.__class__.__slots__ )

edit回答来自O.P.的第一条评论:

当然,这也适用于继承。如果你总是为它们使用对象的所有属性,你就不需要表达式中的" If“部分--在层次结构的顶端,将函数写成_key (而不是在内部为每个类提供唯一名称的__key ),它将适用于你的所有类。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12512511

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档