1

这个问题很容易理解,下面是程序——

hisc = [1,2,3,4]
print("\n", hisc)

ohisc = hisc
hisc.append(5)

print("\nPreviously...", ohisc)
print("\nAnd now...", hisc)
input("\nETE")

当我运行它时,ohisc 得到 5。为什么 ohisc 会改变?我怎样才能阻止它改变?抱歉,如果这是显而易见的事情。

4

3 回答 3

5

Python 变量是引用。因此,赋值复制了引用而不是变量的内容。

为了避免这种情况,您所要做的就是创建一个对象:

ohisc = list(hisc)

这是使用list构造函数从给定的迭代创建一个新列表。

或者,您也可以从切片分配(创建一个新对象):

ohisc = hisc[:]

[]通用切片运算符,用于从给定集合中提取子集。我们只是省略了开始和结束位置(它们分别默认为集合的开始和结束)。

于 2013-03-14T19:53:07.080 回答
2

您绝对需要了解康拉德鲁道夫答案中的所有内容。我认为在你的具体情况下,这也是你想要的。但通常有更好的方法:如果您避免改变对象(即,就地更改它们),那么两个名称是否引用同一个对象都无关紧要。例如,您可以更改:

hisc.append(5)

对此:

hisc = hisc + [5]

这不会hisc就地改变;它创建一个新list的 ,并5在其末尾添加 ,然后将其分配给hisc. 所以,ohisc指向相同list的事实hisc并不重要——它list仍然存在,不变,ohisc指向。

假设您想用 0 替换列表的所有负值。使用突变很容易:

for i in range(len(lst)):
    list[i] = max(list[i], 0)

但更容易没有:

lst = [max(elem, 0) for elem in lst]

现在,如果您想删除每个负面列表元素怎么办?您不能在循环时更改序列的形状,因此您必须制作列表的副本(这样您可以在更改另一个副本时循环一个副本),或者提出一个更复杂的算法(例如,向后交换每个 0,然后删除最后的所有 0)。但是很容易做到一成不变:

lst = [elem for elem in lst if elem >= 0]

那么,你什么时候想要变异?嗯,通常你想要两个对同一个对象的引用,所以当你更新一个时,另一个会看到变化。在这种情况下,您显然必须进行实际更改才能让其他人看到。

于 2013-03-14T21:00:50.050 回答
1

这是对正在发生的事情的一个很好的解释:Python:以正确的方式复制列表

基本上,您正在创建一个指向列表的指针,但您想要做的是制作列表的副本。

试试这个:

hisc = [1,2,3,4]
ohisc = hisc[:]
于 2013-03-14T20:04:06.043 回答