append to a sublist appends to every sublist
我正在编写一个包含10个桶列表的简单哈希表。 索引使用内置的
我尝试过不同的方法定义add_HT,但我一直得到相同的结果。 我究竟做错了什么?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | size = 10 HT = [ [] ] * size def add_HT(data): index = hash(data) % size HT[index].append(data) print HT [[], [], [], [], [], [], [], [], [], []] add_HT('hello') [['hello'], ['hello'], ['hello'], ['hello'], ['hello'], ['hello'], ['hello'], ['hello'], ['hello'], ['hello']] |
您将
1 | HT = [[] for _ in xrange(size)] |
由于已经解释了Volatility和kindall,
他们已经向您展示了如何解决问题并获得10个不同的空
1 2 3 | def add_HT(data): index = hash(data) % size HT[index] = HT[index] + [data] |
现在:
1 2 3 4 | >>> add_HT('hello') >>> add_HT('goodbye') >>> HT [['goodbye'], ['hello'], [], [], [], [], [], [], [], []] |
这里发生的是你每次追加时都要制作一个新桶,并更换旧桶,这样桶就是不可变的。 (您可能希望将它们存储为
您可以更进一步,并且不仅使每个
1 2 3 4 | def add_HT(data): global HT index = hash(data) % size HT = [bucket if i != index else bucket + [data] for i, bucket in enumerate(HT)] |
有时使事物不可变会使代码更简单,有时更复杂。 (在这种情况下,我认为第一个不可变版本与可变版本一样简单,但第二个版本的可读性要低得多。)有时它会使代码更快,有时更慢。 (在这种情况下,快速测试显示第一个速度大约相同,但第二个速度相差50倍,并且使用了更多内存。另一方面,使用PyPy代替CPython,它们反而是15%和30%慢,分别......)但它总是让你更容易推理 - 你不必担心对象的身份。除非它使事情更容易编写,更容易阅读和更快,否则需要考虑一个权衡。但值得知道如何做到这一点。
这是正确的版本:
1 2 3 4 5 6 7 8 9 10 11 | size = 10 HT = [ [] for x in range(size)] def add_HT(data): index = hash(data) % size HT[index].append(data) print HT add_HT('hello') print HT |
输出:
1 2 3 4 | >>> [[], [], [], [], [], [], [], [], [], []] [[], ['hello'], [], [], [], [], [], [], [], []] >>> |