在Python对象中,哪种实现更有效?散列self.\uuuu str\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?

在Python对象中,哪种实现更有效?散列self.\uuuu str\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?,python,Python,为任何给定的Python对象创建股票\uuuuuuuuuuuuuuuuuuuuuu()似乎是一种常见且快速的方法,如果该对象实现了\uuuuuuuuuuuuu(),则返回hash(str(self))。不过,这是否有效?根据,对象属性元组的散列是“好的”,但似乎并不表明它是否是Python最有效的。或者最好为每个对象实现一个\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

为任何给定的Python对象创建股票
\uuuuuuuuuuuuuuuuuuuuuu()
似乎是一种常见且快速的方法,如果该对象实现了
\uuuuuuuuuuuuu()
,则返回hash(str(self))。不过,这是否有效?根据,对象属性元组的散列是“好的”,但似乎并不表明它是否是Python最有效的。或者最好为每个对象实现一个
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

假设我已经从中实现了Jenkins哈希例程。哪个
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

# hash str(self)
def __hash__(self):
    return hash(str(self))

# hash of tuple of attributes
def __hash__(self):
    return hash((self.attr1, self.attr2, self.attr3,
                 self.attr4, self.attr5, self.attr6))

# jenkins hash
def __hash__(self):
    from jenkins import mix, final
    a = self.attr1
    b = self.attr2
    c = self.attr3
    a, b, c = mix(a, b, c)
    a += self.attr4
    b += self.attr5
    c += self.attr6
    a, b, c = final(a, b, c)
    return c

为简单起见,假设示例对象中的属性都是整数。还假设所有对象都派生自一个基类,并且每个对象都实现自己的
\uu str\uu()
。使用第一个散列的折衷办法是,我也可以在基类中实现它,而不向每个派生对象添加额外的代码。但是,如果第二个或第三个
\uuuuuu hash\uuuuu()
实现在某种程度上更好,那么这是否抵消了为每个派生对象添加代码的成本(因为每个派生对象可能具有不同的属性)



编辑:第三个
\uuuuu hash\uuuu()
实现中的
导入
,只是因为我不想起草整个示例模块+对象。假设
import
确实发生在模块顶部,而不是每次调用函数时




结论:根据我的回答和评论,看起来我真的想要元组哈希实现,不是为了速度或效率,而是因为
\uuuuuuuuhash\uuuu
\uuuueq\uu
的潜在双重性。由于散列值将具有某种形式的有限范围(例如,32位或64位),因此在发生散列冲突的情况下,将检查对象相等性。因此,由于我确实通过使用自身/他人属性的元组比较为每个对象实现了
\uuuu eq\uuuu()
,因此我还想实现
\uuuu hash\uuuuu()
使用属性元组,以便我尊重事物的哈希/相等性质。

您的第二个元组有一个重要的性能悲观:每次调用函数时,它都导入两个名称。当然,它相对于字符串哈希版本的性能取决于字符串的生成方式

这就是说,当您有定义对象相等性的属性,并且这些属性本身是可散列类型时,最简单(几乎可以肯定性能最好)的方法是散列包含这些属性值的元组

def __hash__(self):
    return hash((self.attr1, self.attr2, self.attr3))

你不好奇吗,为什么
元组
是可散列的而
列表
不是?我在简化,但这实际上可以帮助你自己回答这个问题。@Tadeck:我实际上不知道元组是可哈希的,而列表不是。我确实使用对象属性的元组来检查相等性,但还没有研究它们的散列实现。我谈论的不是实现细节,而是这样做的原因。另外请注意,
tuple
是不可变的,而
list
是可变的。我应该补充一点,我正在将代码从VB.NET项目转换为Python。NET中没有元组这样的东西,因此每个对象都必须滚动自己的
GetHashCode()
(以及一系列其他相等接口)。@Tadeck:是的,我知道元组是不可变的,而列表不是。是的,我知道导入开销。我不想为这个示例起草一个完整的示例模块+对象,所以我把它放在那里。让我编辑这个问题来说明这一点。关于元组方法,我确实在年读到过,但是,这个答案的创建者只是说它是“好的”,语气暗示可能有更好的方法。在SO上搜索不会发现(在前几页中)针对这个特定主题的问题,所以我想我应该问一下。我想我也应该在问题中添加元组示例?