Python中Set集合中对象的__hash__的问题

2013-09-05 20:07:31 +08:00
 banxi1988
今天测试了下实现set相减的demo。
我发现必须要实现__hash__这个magic方法才可以,但是呢?
感觉又不需要对对象的所以字段都进行hash,如我下面的代码,就可以。
因为set判断元素相等是用__eq__这个magic方法的。那么,我的问题就是,
像我下面的Person对象的__hash__没有对addrs这个进行hash这会有什么问题吗?

https://gist.github.com/banxi1988/6449245
6478 次点击
所在节点    Python
9 条回复
yaroot
2013-09-05 20:34:44 +08:00
摘自文档: A set object is an unordered collection of distinct hashable objects.
keakon
2013-09-05 20:35:08 +08:00
性能从 O(1) 下降到 O(n)
banxi1988
2013-09-05 21:21:40 +08:00
@keakon 请指教,怎么回到O(1)。
banxi1988
2013-09-05 21:23:02 +08:00
@yaroot 你是让我实现__hash__的时候,对可能影响相等判断的值都进行hash吗?
yaroot
2013-09-05 21:29:33 +08:00
@banxi1988 不是我想, 你 print len({ p1, p2, p3, p4, p5 }) 看看
banxi1988
2013-09-05 21:33:45 +08:00
@yaroot print("set len",len({p1,p2,p3,p4,p5})) #output:('set len', 2)
然后呢?
banxi1988
2013-09-05 21:53:38 +08:00
@keakon
我对__hash__时是否对addrs进行hash进行简单的测试,显然是不进行__hash__来得快:
对比如下:
def __hash__(self):
# saddrs = sorted(self.addrs, key=lambda addr:addr.name)
# addrs_str = ''.join([addr.name for addr in saddrs])
return hash((self.name,self.sex))

对addrs进行hashed,构造及比较部分需要的时间:
# with addr hashed ('time=', 4.042909860610962)
不hash时花的时间:
# without addr hashed ('time=', 2.322601795196533)
这样看来不对addrs进行hash是正确的选择喽。那hash用来做什么呢?

@yaroot
yaroot
2013-09-05 23:03:07 +08:00
@banxi1988

http://docs.python.org/2/reference/datamodel.html#object.__hash__
http://docs.python.org/2/glossary.html#term-hashable
被误导了下....但我觉得还是按照文档来实现比较好, 虽然set用__eq__的..

但是按文档这样也会产生冲突, 都是mutable object, 除非你都当它们是immutable的..
这个还是看你实际需求吧...性能瓶颈一般不会在这里
banxi1988
2013-09-06 12:31:04 +08:00
@yaroot 嗯,这样看来,我这样实现也没有什么大的问题,
同样的hash值的对象才会去使用__eq__比较。谢谢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/81446

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX