【问题标题】:Difference between nums[:] = nums[::-1] and nums = nums[::-1] [duplicate]nums[:] = nums[::-1] 和 nums = nums[::-1] 之间的区别 [重复]
【发布时间】:2019-11-30 19:50:58
【问题描述】:

我目前正在学习 Python,但遇到了分配给列表的问题。

def nextPermutation(self, nums: List[int]) -> None:
    ...

我有一行代码将列表反转如下:

nums = nums[::-1]

但测试台将其标记为不正确,而

nums[:] = nums[::-1]

没问题。

我怀疑这是因为我正在创建另一个 nums 列表对象,而传入的原始列表没有改变,对吗?

【问题讨论】:

  • 是的,没错。
  • nums[::-1] 创建一个新列表。将其分配给 nums 对变量的先前值没有影响。将其分配给 nums[:] 会将其填充到现有列表中,替换之前的所有内容。

标签: python python-3.x


【解决方案1】:

如果您了解 C 和指针,您可以将 nums 想象为指向列表的指针。

考虑这种情况:

def reverse(nums):
    nums = nums[::-1]

my_list = [1, 2, 3]
reverse(my_list)

赋值nums = nums[::-1] 相当于在内存中创建一个新列表(元素颠倒),并将指针nums 更改为指向该新列表。但是由于你修改的变量nums是函数的局部变量,所以这个修改对作为参数传递的外部变量没有影响,如下图:

现在考虑这种情况:

def reverse(nums):
   nums[:] = nums[::-1]

my_list = [1, 2, 3]
reverse(my_list)

赋值nums[:] = nums[::-1] 相当于在nums 指向的同一地址写入一个新的反向列表,因为切片允许用新内容替换列表的一部分(尽管在在这种情况下,“部分”是整个列表)。

在这种情况下,您不会更改变量nums,而是更改它指向的数据。如下图所示:

请注意,实际上,python 中的所有变量在此答案中使用的意义上都是“指针”,但只有列表和字典允许“就地”替换某些内容(它们是 可变 数据类型)。对于任何其他类型(不可变),您无法更改内存中的数据,因此您所能做的就是像第一种情况一样“重新分配指针”,这就是函数无法更改作为参数接收的数据的原因,除了对于列表案例。

【讨论】:

  • 只是好奇,您使用什么程序/网站来创建这些图表? (如果这不是秘密)看起来不错,所以赞成...
  • @AndrejKesely 哈哈!这不是秘密。我用过draw.io,很棒,免费,在线
  • 好东西!在我看来,这个答案也应该进入 dup,图表真的很有帮助。
【解决方案2】:

你的假设是完全正确的。

我们可以通过使用内置函数id获取内存中对象的地址来验证这一点

尝试运行这个:

def func(nums):
    print(id(nums),"before change")
    nums[:] = nums[::-1]
    print(id(nums), "after [:]")
    nums = nums[::-1]
    print(id(nums), "after regular assign")

a = [1,2,3]
print(id(a),"original")
func(a)

输出(数字可能不同):

55313512 original
55313512 before change
55313512 after [:]
55297688 after regular assign

如您所见,最后一个 id 返回不同的值,而其余的(来自函数内部和外部)返回相同的值。

【讨论】:

    猜你喜欢
    • 2022-10-17
    • 2016-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-16
    • 2021-11-14
    相关资源
    最近更新 更多