繁体   English   中英

修改 Python function 中的列表

[英]Modifying a list in a Python function

我正在尝试这个简单的 function 的变体:

def reverse_this(thisArray):
    
    saved_first = thisArray[0]
    thisArray = thisArray[1:]
    thisArray.reverse()
    thisArray.insert(0,saved_first)

myList = ['foo', 1,2,3,4,5]
reverse_this(myList)
print('after:', myList)

本质上,我希望它打印出“after: ['foo', 5, 4, 3, 2, 1]”。 但是,这里的切片似乎引起了一些问题。 似乎该列表正在 function 内按预期进行修改,但是,这些更改并未在 function 之外应用到 myList。 这是怎么回事,我该如何解决?

Python 是通过分配传递,用于在 function 内传递 arguments。 当你这样做

thisArray = thisArray[1:]

在您的 function 中,您将传递的参数重新绑定到在您的 function 中创建的新 object 并继续更改thisArray后创建的副本,而不是修改您的参数。 要获取修改后的值,一种方法是从 function 中返回此修改后的列表:

def reverse_this(thisArray):
    saved_first = thisArray[0]
    thisArray = thisArray[1:]
    thisArray.reverse()
    thisArray.insert(0,saved_first)
    return thisArray

myList = ['foo', 1,2,3,4,5]
myList = reverse_this(myList)
print('after:', myList)

另一种方法是修改列表的内容(分配给切片)而不是重新绑定列表本身:

def reverse_this(thisArray):
    saved_first = thisArray[0]
    thisArray[:] = thisArray[1:] # assign to the sliced list's contents
    thisArray.reverse()
    thisArray.insert(0,saved_first)

thisArray通过切片重新分配给新列表 object,因此之后的任何更改都不会影响传递到 function 的原始列表。 请注意列表的实例 ID:

def reverse_this(thisArray):
    
    saved_first = thisArray[0]
    print(f'thisArray pre-slice:  {id(thisArray):#x}')
    thisArray = thisArray[1:]
    print(f'thisArray post-slice: {id(thisArray):#x}')
    thisArray.reverse()
    thisArray.insert(0,saved_first)

myList = ['foo', 1,2,3,4,5]
print(f'myList pre-call:      {id(myList):#x}')
reverse_this(myList)
print(f'myList post-call:     {id(myList):#x}')
print('after:', myList)
myList pre-call:      0x1e2f5713500
thisArray pre-slice:  0x1e2f5713500  # parameter refers to original list
thisArray post-slice: 0x1e2f5753800  # thisArray refers to new list
myList post-call:     0x1e2f5713500  # original list isn't changed.
after: ['foo', 1, 2, 3, 4, 5]

在 Python 中,变量是对象的名称。 如果您对 object 进行变异,则该 object 的所有名称都会“看到”更改。 一个切片生成一个新的 object,在这种情况下,该名称被重新分配给新的 object。

要修复它,请将切片分配到原始列表的整个范围内,这会改变原始列表而不是创建新列表:

def reverse_this(thisArray):
    
    saved_first = thisArray[0]
    thisArray[:] = thisArray[1:]   # replace entire content of original list with slice.
    thisArray.reverse()            # thisArray still refers to original list here.
    thisArray.insert(0,saved_first)

myList = ['foo', 1,2,3,4,5]
reverse_this(myList)
print('after:', myList)
after: ['foo', 5, 4, 3, 2, 1]

分配给切片时,列表的一部分将替换另一个列表。 它不一定必须是相同的大小。

另一个例子:

>>> s = list(range(10))
>>> s
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> id(s)
2339680033664
>>> s[4:7] = [10,10]           # replace indices 4 up to but not including 7
>>> s
[0, 1, 2, 3, 10, 10, 7, 8, 9]
>>> id(s)                           # id didn't change
2339680033664

您可以执行以下操作来实现相同的目的:

def my_reverse(lst):
    lst[1:] = reversed(lst[1:]) # Or lst[:0:-1]

分配给列表切片不会创建任何副本,它只是替换该切片。 看到这个

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM