【问题标题】:Python List Mutation Doesn't Happen When Variable Reassigned. Why?重新分配变量时不会发生 Python 列表突变。为什么?
【发布时间】:2020-08-25 08:23:42
【问题描述】:

这是什么奇怪的魔法?

def rotate_list(lst, n):
    n = n % len(lst)
    lst = lst[-n:] + lst[:-n]
    
def rotate_list_2(lst):
    lst[0], lst[1], lst[2], lst[3] = lst[3], lst[0], lst[1], lst[2]
    
                 
s1 = [1, 2, 5, 4]
rotate_list(s1, 1)
print(s1)

s1 = [1, 2, 5, 4]
rotate_list_2(s1)
print(s1)

输出:

[1, 2, 5, 4]
[4, 1, 2, 5]

看起来虽然列表在函数中通常是可变的,但如果创建了同名列表,则原始列表不受新列表更改的影响。有人可以根据范围和参考来解释这里发生了什么吗?

如何旋转原始列表而无需像rotate_list_2() 那样手动更新每个值?或者这种事情通常会通过处理从函数返回的新列表来完成吗?

【问题讨论】:

  • 因为short-description-of-the-scoping-rules - 你在函数内部创建了一个局部变量。请参阅下文了解如何修复
  • 因为lst[-n:] + lst[:-n] 创建了一个新列表。您的函数只是将其分配给局部变量,并且在函数终止时丢弃该对象。 IOW,rotate_list 根本不会改变列表,而rotate_list_2 会。如果你确实想用这种方法改变列表,你可以做lst[:] = lst[-n:] + lst[:-n]
  • 所以,请阅读以下内容:nedbatchelder.com/text/names.html 注意,这实际上与列表无关。这里的语义总是相同的。 赋值永远不会改变.

标签: python list scope mutability


【解决方案1】:

分配给函数中的列表不会更改原始引用。
该赋值仅引用新值上的本地参数lst
在函数外部(“之前”)引用的原始列表保持不变。

Insead 使用以下语法分配给它的元素:

def rotate_list(lst, n):
    n = n % len(lst)
    lst[:] = lst[-n:] + lst[:-n]

s1 = [1, 2, 5, 4]
rotate_list(s1, 1)

# And it works like magic! :)
# [4, 1, 2, 5]
print(s1)

【讨论】:

  • 所以如果我分配给作为函数参数传入的列表,原始列表将不再对函数可见,而是将创建一个本地列表变量?
  • 对新列表值@RobinAndrews 的引用
  • @RobinAndrews 这是一个参数,始终是本地的。虽然,函数范围内的赋值会创建一个局部变量。但是在这种情况下,由于它是一个参数,它已经是本地的。
【解决方案2】:

如果您重新分配函数的参数,则值不会在函数范围之外更改。

def test0(a):
    a = 10
    print(a)

x = 4
test0(x)
print(x)

这会导致

10
4

为数组赋值的原因是你没有为参数本身赋值。相反,您正在访问数组从中读取的内存,并且您正在更改它。因此,即使对于外部范围,这些更改也会发生。

【讨论】:

    【解决方案3】:

    函数更改后,您可以返回列表并在函数调用中捕获它,如 s=function(s)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-16
      • 2012-06-23
      • 2014-12-21
      • 2015-02-14
      • 1970-01-01
      相关资源
      最近更新 更多