【问题标题】:assigning to list[:] using list comprehension使用列表推导分配给 list[:]
【发布时间】:2018-07-02 11:16:06
【问题描述】:

来自这个答案https://stackoverflow.com/a/1207461/8074522 我正在尝试找出使用

之间的区别
somelist = [1,2,3,4,5,6,7,8,9]
somelist = [x for x in somelist if x>4]
and 
somelist[:] = [x for x in somelist if x>4]

在他的回答中,他说

或者,通过分配给切片 somelist[:],你可以改变现有的 列表仅包含您想要的项目:

“仅包含”

那么需要 somelist[:] here?

【问题讨论】:

  • 分配给somelist 不会更改该名称用于引用的列表,而分配给somelist[:] 会。哪个适合您的情况取决于您的需求细节。

标签: python list-comprehension slice


【解决方案1】:

somelist = [1,2,3,4,5,6,7,8,9] 这样的指令会创建一个新列表并且 将其(整个列表)分配给您的变量 (somelist)。

第二种情况,somelist = [x for x in somelist if x>4] 只是过滤for 循环将此列表中的每个元素分配给一个临时变量 x

然后(在这个循环内)if 检查这个(当前)元素是否满足 某些条件,在您的情况下,是否大于 4。

只有当它存在时,才会将该元素添加到新数组中,最终将 分配给somelist

现在 plain assignment 有什么区别(只针对somelist) 和切片分配(到somelist[:])。

想象一下,最初有 otherList,而您创建了自己的 somelist 使用普通赋值:somelist = otherList

其实当时并没有创建第二个列表,但是somelist可能被认为是 另一个“指向”第一个列表的“指针”。

换句话说,otherListsomelist 都指向相同的内部 对象(在本例中为数组)。

然后,稍后在您的代码中,如果您使用somelist[:] = ...,您将编写新内容 到相同的内部对象,所以这个新内容也可以使用otherList (例如在代码的其他部分)。

但是如果你使用普通赋值(somelist = ...),那么:

  • 创建了一个new内部对象(数组)和somelist点 就为了它。
  • 内容仍显示为otherList

正如 jonrsharpe 指出的那样,使用哪个选项的决定取决于 你的应用真正需要什么。

在最简单的情况下,如果没有其他变量指向“旧” 数组,您可以使用普通赋值(恕我直言,这是一个更自然的选择)和 旧数组(现在没有任何其他变量的引用)将是垃圾 收集。

【讨论】:

  • @leo 他说“原地替换列表并保留相同的对象.. 在您以更好的方式解释之前不清楚.. 谢谢大家,感谢
【解决方案2】:

@jonsharpe 在评论中给出了一个简洁的答案,但为了清楚地说明这一点:

分配一个新列表。丢失对旧列表对象的引用并创建一个新的

>>> lst1 = [[1, 2, 3],[4, 5, 6]]
>>> lst2 = lst1
>>> lst1 = [[7,8,9]]
>>> lst1 is lst2
False
>>> lst1
[[7, 8, 9]]
>>> lst2
[[1, 2, 3], [4, 5, 6]]

分配给切片。 替换列表(或列表的一部分,取决于切片是什么)就地,保持相同的对象。

>>> lst1 = [[1, 2, 3],[4, 5, 6]]
>>> lst2 = lst1
>>> lst1[:] = [[7,8,9]]
>>> lst1 is lst2
True
>>> lst1
[[7, 8, 9]]
>>> lst2
[[7, 8, 9]]

【讨论】:

    猜你喜欢
    • 2012-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-23
    • 1970-01-01
    • 2016-04-18
    • 2021-11-29
    • 1970-01-01
    相关资源
    最近更新 更多