HASH是啥?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HASH是啥?相关的知识,希望对你有一定的参考价值。
hash指的是剁碎的食物。
一、词汇解析:
hash
英 [hæʃ] 美 [hæʃ]
n. 剁碎的食物;混杂,拼凑;重新表述
vt. 搞糟,把…弄乱;切细;推敲
例:The government made a total hash of things and squandered a small fortune.
政府把事情弄得一团糟,还浪费了一笔钱。
二、常用搭配:
hash house 廉价餐馆(经济餐馆)...
hash up 弄糟(使复生)
hash out 通过全面细致讨论后达
hash browns 土豆煎饼
hash method 散列法
扩展资料
近义词
1、farrago
英 [fə'rɑːgəʊ] 美 [fə'rɑɡo]
n. 混杂物;混杂
[ 复数 farragoes ]
例句:The whole story was a farrago of lies and deceit.
整件事是说谎加上欺骗的混杂。
2、mishmash
英 ['mɪʃmæʃ] 美 ['mɪʃmæʃ]
n. 混杂物
vt. 使成为杂乱的一堆
例句:Japanese is turning into a confused mishmash of languages.
日语正变成一个混乱的大杂烩。
参考技术A 是用来加密的一种方式文件校验我们比较熟悉的校验算法有奇偶校验和CRC校验,这2种校验并没有抗数据篡改的能力,它们一定程度上能检测并纠正数据传输中的信道误码,但却不能防止对数据的恶意破坏。
MD5 Hash算法的"数字指纹"特性,使它成为目前应用最广泛的一种文件完整性校验和(Checksum)算法,不少Unix系统有提供计算md5 checksum的命令。
数字签名
Hash 算法也是现代密码体系中的一个重要组成部分。由于非对称算法的运算速度较慢,所以在数字签名协议中,单向散列函数扮演了一个重要的角色。 对 Hash 值,又称"数字摘要"进行数字签名,在统计上可以认为与对文件本身进行数字签名是等效的。而且这样的协议还有其他的优点。
鉴权协议
如下的鉴权协议又被称作"挑战--认证模式:在传输信道是可被侦听,但不可被篡改的情况下,这是一种简单而安全的方法。本回答被提问者采纳 参考技术B 哈希算法将任意长度的二进制值映射为固定长度的较小二进制值,这个小的二进制值称为哈希值。哈希值是一段数据唯一且极其紧凑的数值表示形式。如果散列一段明文而且哪怕只更改该段落的一个字母,随后的哈希都将产生不同的值。要找到散列为同一个值的两个不同的输入,在计算上来说基本上是不可能的。 参考技术C 非典 参考技术D 哈希
百科里面有:
http://baike.baidu.com/view/99075.htm
python中默认的__hash__是啥?
【中文标题】python中默认的__hash__是啥?【英文标题】:What is the default __hash__ in python?python中默认的__hash__是什么? 【发布时间】:2012-07-04 16:09:50 【问题描述】:我经常使用时髦的东西作为字典的键,因此,我想知道正确的方法是什么 - 这通过为我的对象实现良好的哈希方法来实现。我知道这里提出的其他问题,例如good way to implement hash,但我想了解默认的__hash__
如何用于自定义对象,以及是否可以依赖它。
我注意到可变对象是明确不可散列的,因为hash()
引发了一个错误......但奇怪的是,自定义类是可散列的:
>>> class Object(object): pass
>>> o = Object()
>>> hash(o)
那么,有人知道这个默认哈希函数是如何工作的吗?通过了解这一点,我想知道:
如果我将相同类型的对象作为字典的键,我可以依赖这个默认哈希吗?例如:
key1 = MyObject()
key2 = MyObject()
key3 = MyObject()
key1: 1, key2: 'blabla', key3: 456
如果我使用不同类型的对象作为字典中的键,我可以依赖它吗?例如
int: 123, MyObject(10): 'bla', 'plo': 890
在最后一种情况下,如何确保我的自定义哈希不会与内置哈希冲突?例如:
int: 123, MyObject(10): 'bla', MyObjectWithCustomHash(123): 890
【问题讨论】:
***.com/a/2909119/174728 @gnibbler :已经知道了 - 请参阅问题中的链接 无关,但需要注意的一点是,“如果您要覆盖__hash__
,请同时覆盖 __eq__
。”
User-defined classes have __eq__() and __hash__() methods by default; with them, all objects compare unequal (except with themselves) and x.__hash__() returns an appropriate value such that x == y implies both that x is y and hash(x) == hash(y).
docs.python.org/3/reference/datamodel.html#object.__hash__
【参考方案1】:
您可以依赖的:自定义对象有一个默认的hash()
,它以某种方式基于对象的身份。即,任何使用默认哈希的对象在其生命周期内都将具有该哈希的常量值,并且不同的对象可能具有也可能没有不同的哈希值。
您不能依赖id()
返回的值与hash()
返回的值之间的任何特定关系。在 Python 2.6 及更早版本的标准 C 实现中,它们是相同的,在 Python 2.7-3.2 hash(x)==id(x)/16
。
编辑:最初我写道,在 3.2.3 及更高版本或 2.7.3 或更高版本中,哈希值可能是随机的,而在 Python 3.3 中,这种关系将始终是随机的。事实上,目前随机化只适用于散列字符串,所以实际上除以 16 的关系可能会继续存在,但不要指望它。
哈希冲突通常无关紧要:在字典查找中查找对象必须具有相同的哈希并且还必须比较相等。只有当您遇到非常高比例的冲突(例如导致最近版本的 Python 能够随机化哈希计算的拒绝服务攻击)时,冲突才有意义。
【讨论】:
【参考方案2】:documentation 声明自定义对象依赖 id()
作为其 hash()
实现:
CPython 实现细节:这是对象在内存中的地址。
如果您将自定义对象与 int
等内置类型混合使用,它们可能会发生哈希冲突,但如果它们是均匀分布的,那根本没有问题。除非您真的遇到性能问题,否则不要进行过多调查。
【讨论】:
那么,你的意思是如果我只使用自定义类型,就不应该有冲突吗? 对,id是唯一的。其他类型的问题是它们不一定使用id()
,但通常使用更合理的哈希值;例如整数只使用它们的值作为它们的哈希值。
所以:int: 123, MyObject(): 465, MyType: 890
应该是安全的,对吧?
另外......让我再说一遍,尽管文档说的是 Python 2.7 id(custom_obj) != hash(custom_obj)
它们是“安全的”,尽管它们可能是哈希冲突。它只是一个性能问题。对于您的问题,不,如果您的键不仅仅是自定义对象实例,它们可能会发生哈希冲突。【参考方案3】:
在 Python 3 中,以下函数用于 object
的子类,以对抗对象的 id()
(来自 pyhash.c
)
Py_hash_t
_Py_HashPointer(void *p)
Py_hash_t x;
size_t y = (size_t)p;
/* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid
excessive hash collisions for dicts and sets */
y = (y >> 4) | (y << (8 * SIZEOF_VOID_P - 4));
x = (Py_hash_t)y;
if (x == -1)
x = -2;
return x;
SIZEOF_VOID_P
对于 64 位 Python 为 8,对于 32 位 Python 为 4。
>>> class test: pass
...
>>> a = test()
>>> id(a)
4325845928
>>> hash(a)
-9223372036584410438
您可以看到哈希是使用公式(id(a) >> 4) | (id(a) << (8 * SIZEOF_VOID_P - 4))
从id(a)
计算得出的,其中对C
有符号整数执行按位运算。例如,对于上面定义的a
:
>>> import numpy
>>> y = numpy.array([4325845928], dtype='int64')
>>> SIZEOF_VOID_P = 8
>>> (y >> 4) | (y << (8 * SIZEOF_VOID_P - 4))
array([-9223372036584410438])
请注意,我使用的是numpy.array(dtype='int64')
,因此按位运算的行为方式与在 C 中的方式相同(如果您对 Python 整数执行相同的操作,则会得到不同的行为,因为它们不会溢出)。见https://***.com/a/5994397/161801。
【讨论】:
According to Duncan – 在 Python 3.3 中,id()
和 hash()
之间甚至没有固定的关系。
@PiotrDobrogost 存在固定关系。这是(id(x) >> 4) | (id(x) << (8 * SIZEOF_VOID_P - 4))
。我在此处粘贴的代码取自 Python 3 源代码。 d
(_Py_HashPointer
函数的输入)是对象的内存地址,即它的id()
。运行SIZEOF_VOID_P = 8; y = numpy.array([4325845928], dtype='int64'); print((y >> 4) | (y << (8 * SIZEOF_VOID_P - 4)))
。结果是-9223372036584410438,对应于我上面展示的例子。
我认为 Duncan 的意思是 Python 3.3 中引入的哈希随机化。但是,它目前仅对字符串有效,您显示的代码可能适用于一般情况。
size_t 在 C 中是无符号的(未签名),所以正如评论所说,这是一个滚动操作【参考方案4】:
用户定义类的默认哈希是只返回它们的 id。这给出了一种通常有用的行为;使用用户定义类的实例作为字典键将允许在再次提供完全相同的对象以查找值时检索关联的值。例如:
>>> class Foo(object):
def __init__(self, foo):
self.foo = foo
>>> f = Foo(10)
>>> d = f: 10
>>> d[f]
10
这匹配用户定义类的默认相等性:
>>> g = Foo(10)
>>> f == g
False
>>> d[g]
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
d[g]
KeyError: <__main__.Foo object at 0x0000000002D69390>
请注意,尽管f
和g
的属性值相同,但它们并不相等,并且在d
中查找g
时找不到存储在f
下的值。此外,即使我们更改了f.foo
的值,在d
中查找f
仍然可以找到该值:
>>> f.foo = 11
>>> d[f]
10
假设一些任意新类的实例应该被视为非等价的,除非程序员通过定义 __eq__
和 __hash__
明确声明两个实例被视为等价的条件。
这非常有效;如果我定义一个Car
类,我可能认为两辆具有相同属性的汽车代表两辆不同的汽车。如果我有一本将汽车映射到注册车主的字典,我不想在查找 Bob 的汽车时找到 Alice,即使 Alice 和 Bob 碰巧拥有相同的汽车! OTOH,如果我定义一个类来表示邮政编码,我可能确实想考虑两个具有相同代码的不同对象是“相同”事物的可互换表示,在这种情况下,如果我有一个将邮政编码映射到州的字典,我显然希望能够找到代表相同邮政编码的两个不同对象的相同状态。
我将此称为“值类型”和“对象类型”之间的区别。值类型代表一些值,它是我关心的 值,而不是每个单独对象的身份。产生相同值的两种不同方法同样好,并且传递值类型的代码的“合同”通常只是承诺为您提供具有某些值的对象,而不指定它是哪个特定对象。对于对象类型 OTOH,每个单独的实例都有自己的标识,即使它包含与另一个实例完全相同的数据。围绕对象类型传递的代码“契约”通常承诺跟踪确切的单个对象。
那么为什么内置的可变类不使用它们的 id 作为它们的哈希呢?这是因为它们都是容器,我们通常认为容器大多类似于值类型,它们的值由包含的元素决定:
>>> [1, 2, 3] == [1, 2, 3]
True
>>> f: 10 == f: 10
True
但可变容器的值是transient。某些给定列表当前 具有值[1, 2, 3]
,但它可以变异为具有值[4, 5, 6]
。如果您可以使用列表作为字典键,那么我们必须就查找是否应该使用列表的(当前)值或其标识做出裁决。无论哪种方式,当当前用作字典键的对象的值通过变异来更改时,我们都会(非常)惊讶。仅当对象的值是其标识,或者对象的标识与其值无关时,将对象用作字典键才有效。所以 Python 选择的答案是声明可变容器不可散列。
现在,回答您的直接问题的更具体细节:
1) 由于 CPython 中的默认哈希值(尽管根据其他答案/cmets 显然只有
2) 只要您不返回与某个现有对象的哈希值完全相同的结果作为您的自定义哈希值,您就应该相对没问题。我的理解是,Python 的基于散列的容器相对可以容忍次优散列函数,只要它们没有完全退化。
【讨论】:
【参考方案5】:>>> class C(object):
... pass
...
>>> c = C()
>>> hash(c) == id(c)
True
查看函数id
【讨论】:
我在 Python 2.7 和 3.2 上得到False
,但在 Python 2.6 上得到 True
。
旧版本的 CPython 直接使用 id()
的值作为默认的 hash()
,新版本使用 id()/16
因为在 CPython 中所有 id 都是 16 的倍数,并且您想要低位放。这纯粹是一个实现细节:默认的hash()
是从id()
生成的,但确切地说是版本之间的变化。在 Python 3.3 中,id()
和 hash()
之间甚至没有固定的关系。
@Duncan 为什么要除以 16?为什么所有 id 都是 16 的倍数,并且想要设置低位?
Python 对象与内存字长对齐,因此对于 64 位解释器,这意味着每个对象都与 16 的倍数对齐。id 只是内存地址,因此所有 id 都是16. 这很重要,因为当您遇到哈希冲突时,会使用最低 5 位从旧哈希计算新哈希,如果其中 4 位始终为 0,那么您很有可能再次发生冲突。【参考方案6】:
>>> class C(object):
... pass
...
>>> c = C()
>>> hash(c) == id(c)
False
>>> hash(c) == id(c)/16
True
除以 16 为真
【讨论】:
复制 3 年前发布的答案几乎没有用处。以上是关于HASH是啥?的主要内容,如果未能解决你的问题,请参考以下文章