附加到子列表附加到每个子列表

2024-09-30 20:19:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在写一个包含10个存储桶列表的简单哈希表。使用内置的hash()计算索引,然后对表大小进行模化。但是,当我尝试在bucket对象的每一个bucket中追加它时,我会尝试在bucket对象上追加它。 我试着用不同的方法来定义,但结果总是一样的。我做错什么了?在

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']]

Tags: 对象方法addhello列表datasizeindex
3条回答

{cd1>定义一个引用列表。相反,定义如下:

HT = [[] for _ in xrange(size)]

正如Volatility和kindall已经解释过的,HT = [ [] ] * size复制了10个相同的空list,而不是10个不同的空lists。list身份总是让新手程序员头疼,有时甚至连专家也会被咬。在

他们已经向您展示了如何解决这个问题并得到10个不同的空lists,但是还有另一种方法可以解决这个问题。如果您可以重写程序以完全不改变list,那么它们是否相同并不重要:

def add_HT(data):
    index = hash(data) % size
    HT[index] = HT[index] + [data]

现在:

^{pr2}$

这里的情况是,每次追加时都会生成一个新的bucket,并替换旧的bucket,所以bucket是不可变的。(您可能希望将它们存储为tuples,而不是lists,以确保不会意外地使它们突变。)

您可以更进一步,不仅使每个HT[i]不可变,而且使HT本身保持不变:

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%。)但这总是让你更容易思考,不必担心对象身份。除非它使事情更容易写,更容易阅读,而且更快,有一个折衷,你必须考虑。但知道怎么做是值得的。在

HT = [ [] ] * size使size指向同一列表的指针数目。add_HT不是这里的问题。您需要将HT定义为[[] for i in xrange(size)]。在

相关问题 更多 >