1
fox0001 2017-07-26 12:01:33 +08:00 via Android
那要 key 来干嘛?
|
2
wwqgtxx 2017-07-26 12:10:34 +08:00
当然可以了
Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> class A: ... pass ... >>> {A():1,A():2} {<__main__.A object at 0x0000026C84DA32E8>: 1, <__main__.A object at 0x0000026C84DA3320>: 2} >>> |
3
pythongo 2017-07-26 12:17:45 +08:00
字典的 key 是不可变,能 hash 的, 你去看字典 key 的限制,只要符合规范当然可以
|
4
siteshen 2017-07-26 12:20:55 +08:00
1. 代码能不能跑?跑一下就知道了。
2. 为什么能(不能)跑?参考 3 楼的答案。 |
5
ivechan 2017-07-26 12:42:12 +08:00
能 hash 的都能.
|
6
bccber OP |
7
HypoChen 2017-07-26 13:52:24 +08:00
|
8
bccber OP def __hash__(self): 和 __eq__ ??
|
10
PythonAnswer 2017-07-26 14:00:24 +08:00 via Android
汽车能当钥匙使吗?能啊。但是有些浪费。
|
11
cy18 2017-07-26 14:03:35 +08:00 via Android
hash 是辅助判断的,主要是 eq。要确保 eq 的两个对象 hash 必须相等,反之不一定。
最坏情况,hash 全部返回 0 都没关系,只不过会导致速度很慢。 反之如果 hash 不等但是 eq 的话就会出问题。比如用 id 做 hash 然后用成员变量值判断 eq。 |
12
bccber OP hash 只是为了快速判断
当 hash 一样 会使用 eq 再判断 是吧 |
13
bccber OP ok 了
|
14
bccber OP @PythonAnswer 你竟然没碰到过必须要使用类或者结构体作 key 的场景?
|
15
CryMeatel 2017-07-26 14:15:17 +08:00
@bccber 一般这样的需求,我都是直接把数据套入现成可 hash 化容器的,比如 tuple, namedtuple ;其实类作为 key 也是为了对其成员变量做个区分吧
|
16
bccber OP |
17
wwqgtxx 2017-07-26 17:12:08 +08:00 via iPhone
@bccber python 的 dict 并不考虑你的__hash__和__eq__,他是直接比较内存地址的
|
18
wwqgtxx 2017-07-26 18:12:47 +08:00
刚才没注意,python 的 dict 会考虑__eq__的,测试方法如下
>>> class A: ... def __hash__(): ... return 1 ... >>> >>> class A: ... def __hash__(self): ... return 1 ... def __eq__(self,a): ... return True ... >>> {A():1,A():2} {<__main__.A object at 0x0000026C84DA3D30>: 2} >>> class A: ... def __hash__(self): ... return 1 ... >>> {A():1,A():2} {<__main__.A object at 0x0000026C84DA3320>: 1, <__main__.A object at 0x0000026C84DA3D68>: 2} >>> |
19
pythongo 2017-07-26 19:32:02 +08:00
A dictionary ’ s keys are almost arbitrary values. Values that are not hashable, that is, values containing lists, dictionaries or other mutable types (that are compared by value rather than by object identity) may not be used as keys.
hashable An object is hashable if it has a hash value which never changes during its lifetime (it needs a __hash__() method), and can be compared to other objects (it needs an __eq__() or __cmp__() method). Hashable objects which compare equal must have the same hash value. Hashability makes an object usable as a dictionary key and a set member, because these data structures use the hash value internally. All of Python ’ s immutable built-in objects are hashable, while no mutable containers (such as lists or dictionaries) are. Objects which are instances of user-defined classes are hashable by default; they all compare unequal (except with themselves), and their hash value is derived from their id(). |
20
PythonAnswer 2017-07-26 19:54:17 +08:00 via Android
|
21
CryMeatel 2017-07-26 19:58:31 +08:00
@bccber 哈哈, 但实际上 tuple 是 python 文档里面推荐的可 hash 可对比的不变容器,用来做 Key 合适不过了。
不过你一定要确认的话,tuple 实现都是 C 代码,要看去看解释器源码了。 |
22
linw1995 2017-07-26 22:04:29 +08:00
>>> from collections.abc import Hashable
>>> mutable = [list, bytearray, set, dict] >>> immutable = [int, float, complex, str, tuple, frozenset, bytes] >>> all(isinstance(x(), Hashable) for x in immutable) True >>> all(issubclass(x, Hashable) for x in immutable) True >>> any(isinstance(x(), Hashable) for x in mutable) False >>> any(issubclass(x, Hashable) for x in mutable) 基本类型里,不可变的都是可 hash 的。无论是有序的 Tuple 还是无序的 frozenset,因为其是不可变的,都是可 hash 的。所以都可以当 mapping 的 key。 若是要自定义可 hash 的对象,就一定要实现__hash__、__eq__两个方法。 若是不实现,也可以 hash。这是因为类缺省__hash__、__eq__两个方法,但是其依据是 id 值,那么结果就不是我们想要的。 参考: https://wiki.python.org/moin/DictionaryKeys#User_Defined_Types_as_Dictionary_Keys http://www.laurentluce.com/posts/python-dictionary-implementation/ |