简体   繁体   中英

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?

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. spam = eggs doesn't have a value. And so on.


Secondarily, the comprehension style feeds very well into the iterable paradigm, which is fundamental to 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.


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 . (And a lot of work has gone into optimizing the hell out of list.sort ; it's not just an afterthought.)

Python doesn't stop you from doing it. 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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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