关于在Python函数中就地修改列表的方法

时间:2018-06-21 18:28:14

标签: python in-place

如果我尝试通过以下方式就地修改“木板”列表,则无法正常工作,看来它会生成一些新的“木板”,而不是就地修改。

def func(self, board):
    """
    :type board: List[List[str]]
    """
    board = [['A' for j in range(len(board[0]))] for i in range(len(board))]

    return 

我必须做这样的事情才能就地进行修改,这是什么原因?谢谢。

    for i in range(len(board)):
        for j in range(len(board[0])):
            board[i][j] = 'A'

2 个答案:

答案 0 :(得分:2)

您似乎了解这两种情况之间的区别,并且想知道为什么Python使您以不同的方式处理它们?

  

我必须做这样的事情才能对其进行修改,这是什么原因?


创建新副本是有价值的。因此,使其成为一种表达是有意义的。实际上,列表推导如果不是表达式,将毫无用处。

就地更改列表是没有价值的。因此,没有理由使其成为表达式,实际上这样做很奇怪。当然,您可以提出某种价值(例如,列表被突变)。但这与Python设计中的其他所有内容都不一致:spam.append(eggs)不返回spam,它什么也不返回。 spam = eggs没有值。依此类推。


其次,理解风格很好地融入了可迭代的范式,这是Python的基础。例如,请注意,只需将[…]更改为(…),就可以将列表推导转换为生成器推导(这使您可以对按需计算的值进行延迟迭代)。突变会有什么有用的等效物?

使转换副本更方便也鼓励人们使用非变异样式,这通常可以为许多问题提供更好的答案。当您想知道如何避免编写三行嵌套语句来对某些全局变量进行突变时,答案是停止对该全局变量进行突变,而是传入一个参数并返回新值。

此外,该语法是从Haskell复制而来的,那里没有 突变。


但是,所有那些“经常”和“通常”并不意味着“从不”。有时(除非您设计的语言没有变异),否则您需要就地执行操作。这就是为什么我们同时拥有list.sortsorted的原因。 (而且,从list.sort到优化地狱已经做了很多工作;这不仅仅是事后的想法。)

Python不会阻止您执行此操作。它只是不会轻易弯曲 ,就像复制一样容易。

答案 1 :(得分:0)

那没有修改它。列表理解语法[x for y in z]正在创建一个新列表。此语法不会修改原始列表。将函数内部的名称指向新列表不会更改函数外部所指向的列表。

换句话说,当调用函数时,python传递对对象的引用,而不是对名称的引用,因此没有简单的方法来更改函数外部引用的变量名称。