Python 3.2中如何实现__hash__? [英] How __hash__ is implemented in Python 3.2?

查看:92
本文介绍了Python 3.2中如何实现__hash__?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使自定义对象可以哈希(通过酸洗)。我可以为Python 2.x找到 __ hash __ 算法(参见下面的代码),但它显然与Python 3.2的hash不同(我想知道为什么? )。有人知道如何在Python 3.2中实现 __ hash __ 吗?

  #Version: Python 3.2 

def c_mul(a,b):
#C类型乘法
return eval(十六进制((int(a)* b)& 0xFFFFFFFF)[: 1])$ ​​b
$ b class hs:
#Python 2.x散列算法http://effbot.org/zone/python-hash.htm
def __hash __(self ):
如果不是self:
return 0#empty
value = ord(self [0])<<
value = c_mul(1000003,value)^ ord(char)
value = value ^ len(self)
if value == -1:
value = -2
返回值

$ b def main():
s = [PROBLEM,PROBLEN,PROBLEO, PROBLEP]#,PROBLEQ,PROBLER,PROBLES]
print(Python 3.2 hash()bild-in)
for s [:]:print(hash ('',c,'')=,hex(hash(c)),end =\\\

print(\\\

print(Python 2。对于c中的s [:]:print(hs .__ hash __(',c,')=,hex(hs .__ hash __(c)),end =\\\



if __name__ ==__main__:
main()






  OUTPUT:
Python 3.2 hash()bild-in
hash('PROBLEM')= 0x7a8e675a
hash('PROBLEN')= 0x7a8e6759
hash('PROBLEO')= 0x7a8e6758 $ b $ hash('PROBLEP')= 0x7a8e6747


Python 2.x类型的哈希:__hash__ ()
hs .__ hash __('PROBLEM')= 0xa638a41
hs .__ hash __('PROBLEN')= 0xa638a42
hs .__ hash __('PROBLEO')= 0xa638a43
hs。 __hash __('PROBLEP')= 0xa638a5c

编辑: Python 3.2哈希值现在是新类型的值,Py_hash_t等。



Edit2 @Pih谢谢[link] http://svn.python.org/view/python/trunk /Objects/stringobject.c?view=markup

  static long 
1263 string_hash(PyStringObject * a )
1264 {
1265寄存器Py_ssize_t len;
1266寄存器无符号字符* p;
1267寄存器长x;
1268
1269 if(a-> ob_shash!= -1)
1270 return a-> ob_shash;
1271 len = Py_SIZE(a);
1272 p =(unsigned char *)a-> ob_sval;
1273 x = * p < 7; (--len> = 0)
1275 x =(1000003 * x)^ * p ++;
1276 x ^ = Py_SIZE(a);
1277 if(x == -1)
1278 x = -2;
1279 a-> ob_shash = x;
1280 return x;
1281}


解决方案

不同的是写在那里:


哈希值现在是一个新的
类型的值,Py_hash_t被定义为
与指针大小相同。
之前它们的类型是long,
,在一些64位操作系统上
仍然只有32位长。


哈希也考虑计算新值,看一看

  sys.hash_info 

对于字符串,您可以看看 http://svn.python.org/view/python/trunk/Objects/stringobject.c?view=markup < a>第1263行string_hash(PyStringObject * a)

I want to make custom object hash-able (via pickling). I could find __hash__ algorithm for Python 2.x (see code below), but it obviously differs from hash for Python 3.2 (I wonder why?). Does anybody know how __hash__ implemented in Python 3.2?

#Version: Python 3.2

def c_mul(a, b):
    #C type multiplication
    return eval(hex((int(a) * b) & 0xFFFFFFFF)[:-1])

class hs:
    #Python 2.x algorithm for hash from http://effbot.org/zone/python-hash.htm
    def __hash__(self):
        if not self:
            return 0 # empty
        value = ord(self[0]) << 7
        for char in self:
            value = c_mul(1000003, value) ^ ord(char)
        value = value ^ len(self)
        if value == -1:
            value = -2
        return value


def main():
    s = ["PROBLEM", "PROBLEN", "PROBLEO", "PROBLEP"]#, "PROBLEQ", "PROBLER", "PROBLES"]
    print("Python 3.2 hash() bild-in")
    for c in s[:]: print("hash('", c, "')=", hex(hash(c)),  end="\n")
    print("\n")
    print("Python 2.x type hash: __hash__()")
    for c in s[:]: print("hs.__hash__('", c, "')=", hex(hs.__hash__(c)),  end="\n")


if __name__ == "__main__":
    main()


OUTPUT:
Python 3.2 hash() bild-in
hash(' PROBLEM ')= 0x7a8e675a
hash(' PROBLEN ')= 0x7a8e6759
hash(' PROBLEO ')= 0x7a8e6758
hash(' PROBLEP ')= 0x7a8e6747


Python 2.x type hash: __hash__()
hs.__hash__(' PROBLEM ')= 0xa638a41
hs.__hash__(' PROBLEN ')= 0xa638a42
hs.__hash__(' PROBLEO ')= 0xa638a43
hs.__hash__(' PROBLEP ')= 0xa638a5c

Edit: Difference explained, for Python 3.2 "Hash values are now values of a new type, Py_hash_t,etc.."

Edit2 @Pih Thanks [link] http://svn.python.org/view/python/trunk/Objects/stringobject.c?view=markup

static long
1263    string_hash(PyStringObject *a)
1264    {
1265        register Py_ssize_t len;
1266        register unsigned char *p;
1267        register long x;
1268    
1269        if (a->ob_shash != -1)
1270            return a->ob_shash;
1271        len = Py_SIZE(a);
1272        p = (unsigned char *) a->ob_sval;
1273        x = *p << 7;
1274        while (--len >= 0)
1275            x = (1000003*x) ^ *p++;
1276        x ^= Py_SIZE(a);
1277        if (x == -1)
1278            x = -2;
1279        a->ob_shash = x;
1280        return x;
1281    }

解决方案

The answer why they are different is written there:

Hash values are now values of a new type, Py_hash_t, which is defined to be the same size as a pointer. Previously they were of type long, which on some 64-bit operating systems is still only 32 bits long.

The hashing also consider new values to be calculate, take a look at

 sys.hash_info 

For strings, you can take a look at http://svn.python.org/view/python/trunk/Objects/stringobject.c?view=markup line 1263 string_hash(PyStringObject *a)

这篇关于Python 3.2中如何实现__hash__?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆