我不能在函数内更改列表吗?

时间:2018-11-19 15:33:48

标签: python list

# left rotate using slicing
def leftRotate(arr, k, n):
    arr = arr[k:] + arr[:k]
    print(arr)

arr = [1, 2, 3, 4, 5, 6, 7] 
leftRotate(arr, 2, 7) 
print(arr)

结果:

[3, 4, 5, 6, 7, 1, 2]
[1, 2, 3, 4, 5, 6, 7]

当我在函数外部打印数组时,它不再旋转并且保持原来的样子。有人可以帮我理解吗?

4 个答案:

答案 0 :(得分:6)

是的,您可以在函数中更改列表,但是您需要使用正确的语法。如您所见,这不是正确的方法:

def leftRotate(arr, k, n):
    arr = arr[k:] + arr[:k]

我将尽力解释为什么这种方法不起作用,并希望给您更好的直觉。在上面显示的函数范围内,有3个局部变量:arrkn。右侧操作arr[k:] + arr[:k]在不修改原始列表的情况下创建了一个新的列表对象,并且此结果对象绑定到局部变量名称arr。这不会修改原始对象,因为Python中的此类赋值语句是从不变异对象。它们只会在名称空间中绑定名称。 考虑一下,就好像您要从旧列表对象中删除名称标签“ arr” 一样,该标签作为参数传入,并粘贴在新列表对象上刚刚创建的。此类操作不会修改旧列表对象,只能修改本地名称空间-旧列表对象变为“匿名”,并且在此范围内不再可以访问。

解决方案是使用另一种赋值语句,即 slice赋值,它会发生变化:

def leftRotate(arr, k, n):
    arr[:] = arr[k:] + arr[:k]

最后一点,stdlib中有一个类似列表的数据结构,它提供了更高效的循环操作(以对集合中间的索引效率较低的代价为代价)。如果您对此感兴趣,请阅读collections.deque上的文档。

答案 1 :(得分:2)

问题在于列表切片没有在适当位置应用 。有效地创建了一个 new 列表,并将其分配给范围为arr的变量leftRotate,即只能在您的函数中访问它。可以正常运行的方法 可以按预期工作:

def rev_sort(arr, k, n):
    arr.sort(reverse=True)
    print(arr)

arr = [1, 2, 3, 4, 5, 6, 7] 
rev_sort(arr, 2, 7) 

print(arr)

[7, 6, 5, 4, 3, 2, 1]
[7, 6, 5, 4, 3, 2, 1]

在您的示例中,您可以让函数返回一个列表并将其分配给arr

def leftRotate(arr, k, n):
    arr = arr[k:]+arr[:k]
    print(arr)
    return arr

arr = [1, 2, 3, 4, 5, 6, 7] 
arr = leftRotate(arr, 2, 7) 
print(arr)

[3, 4, 5, 6, 7, 1, 2]
[3, 4, 5, 6, 7, 1, 2]

答案 2 :(得分:2)

您的问题是,由于范围的原因,您无法在python函数内更改变量。 Read this了解更多信息。

但是继续,您需要返回arr并将其分配到外部。像这样:

#left rotate using slicing
def leftRotate(arr, k, n):
    arr=arr[k:]+arr[:k]
    return arr

arr = [1, 2, 3, 4, 5, 6, 7] 
arr = leftRotate(arr, 2, 7) 
print arr

或者,如果您愿意,可以将arr设为全局。 (有关更多信息,请检查this)。 (不建议使用最后一个,但是存在)

arr = [1, 2, 3, 4, 5, 6, 7]

#left rotate using slicing
def leftRotate( k, n):
    global arr
    arr=arr[k:]+arr[:k]

leftRotate( 2, 7) 
print arr

希望对您有所帮助:)

答案 3 :(得分:-5)

有很多非常复杂的答案。这是“傻瓜”版本:

  • 您要将arr传递到leftRotate()
  • 几乎所有目的,您都可以认为这是在创建另一个变量,也称为arrleftRotate()在此变量上起作用。 leftRotate()的{​​{1}}与您要传递给arr的{​​{1}} 不同。它是副本(从技术上讲,它不是副本,除非您将arr分配给其他对象,但必须足够接近这些目的)。
  • 您不会再将修改后的leftRotate()arr中撤回。

您可以通过两种方式解决此问题:

  • arr之外定义leftRotate(),并且不要传入arr。我将其称为“ leftRotate()”方法。不推荐使用,除非您有非常充分理由。
  • 功能完成后,请使用arr。本质上,global的意思是return arr。在99.99999%的情况下,这就是您想要的。

因此,在您的示例中,您真正想要的是:

return 'x'