简体   繁体   English

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

[英]About the way to modify the list in-place in a function in Python

If I try to modify the 'board' list in-place in the way below, it doesn't work, it seems like it generate some new 'board' instead of modify 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 

I have to do something like this to modify it in-place, what's the reason? 我必须做这样的事情才能就地进行修改,这是什么原因? Thanks. 谢谢。

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

You seem to understand the difference between these two cases, and want to know why Python makes you handle them differently? 您似乎了解这两种情况之间的区别,并且想知道为什么Python使您以不同的方式处理它们?

I have to do something like this to modify it in-place, what's the reason? 我必须做这样的事情才能就地进行修改,这是什么原因?


Creating a new copy is something that has a value. 创建新副本是有价值的。 So it makes sense for it to be an expression. 因此,使其成为一种表达是有意义的。 In fact, list comprehensions would be useless if they weren't expressions. 实际上,列表推导如果不是表达式,将毫无用处。

Mutating a list in-place isn't something that has a value. 就地改变列表是没有价值的。 So, there's no reason to make it an expression, and in fact, it would be weird to do so. 因此,没有理由使其成为表达式,实际上这样做很奇怪。 Sure, you could come up with some kind of value (like, say, the list being mutated). 当然,您可以提出某种价值(例如,列表被突变)。 But that would be at odds with everything else in the design of Python: spam.append(eggs) doesn't return spam , it returns nothing. 但这与Python设计中的其他所有内容都不一致: spam.append(eggs)不返回spam ,它不返回任何内容。 spam = eggs doesn't have a value. spam = eggs没有价值。 And so on. 等等。


Secondarily, the comprehension style feeds very well into the iterable paradigm, which is fundamental to Python. 其次,理解风格很好地融入了可迭代的范式,这是Python的基础。 For example, notice that you can turn a list comprehension into a generator comprehension (which gives you a lazy iterator over values that are computed on demand) just by changing the […] to (…) . 例如,请注意,只需将[…]更改为(…) ,就可以将列表推导转换为生成器推导(这使您可以对按需计算的值进行延迟的迭代(…) What useful equivalent could there be for mutation? 突变会有什么有用的等效物?

Making the transforming-copy more convenient also encourages people to use a non-mutating style, which often leads to better answers for many problems. 使转换副本更方便也鼓励人们使用非变异样式,这通常可以为许多问题提供更好的答案。 When you want to know how to avoid writing three lines of nested statement to mutate some global, the answer is to stop mutating that global and instead pass in a parameter and return the new value. 当您想知道如何避免编写三行嵌套语句来对某些全局变量进行突变时,答案是停止对该全局变量进行突变,而是传递一个参数并返回新值。

Also, the syntax was copied from Haskell, where there is no mutation. 此外,语法是从Haskell中,在没有突变的复制。


But of course all those "often" and "usually" don't mean "never". 但是,所有那些“经常”和“通常”并不意味着“从不”。 Sometimes (unless you're designing a language with no mutation), you need to do things in-place. 有时(除非您设计的语言没有变异),否则您需要就地执行操作。 That's why we have list.sort as well as sorted . 这就是为什么我们list.sort以及sorted (And a lot of work has gone into optimizing the hell out of list.sort ; it's not just an afterthought.) (并且已经做了很多工作来优化list.sort的地狱;这不仅仅是事后的想法。)

Python doesn't stop you from doing it. Python不会阻止您这样做。 It just doesn't bend over quite as far to make it easy as it does for copying. 它只是不弯腰远,使之容易,因为它为复制。

that is not modifying it in place. 那没有修改它。 The list comprehension syntax [x for y in z] is creating a new list. 列表理解语法[x for y in z]在创建一个新列表。 The original list is not modified by this syntax. 此语法不会修改原始列表。 Making the name inside the function point to a new list won't change what list the name outside the function is pointing. 使函数内部的名称指向新列表不会更改函数外部名称所指向的列表。

In other words, when calling a function python passes a reference to the object, not the name, so there is no easy way to change which object the variable name outside the function is refering to. 换句话说,当调用函数时,python传递对对象的引用,而不是对名称的引用,因此,没有简单的方法来更改函数外部的变量名所指向的对象。

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

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