List as a function argument - modifications discarded

北慕城南 提交于 2019-12-25 06:54:20

问题


I have a following code

def hidePasswords(L, password):
    for elem in L:
        if elem == password:
            elem = "*"*len(password)
    return L

print(hidePasswords(["test","test1","test8"],"test"))

It returns ['test', 'test1', 'test8'] instead of ['****', 'test1', 'test8']. When I change my function to

def hidePasswords(L, password):
    temp = []
    for elem in L:
        if elem == password:
            elem = "*"*len(password)
        temp.append(elem)
    return temp

it works correctly.

Why does Python behaves in such a way? I perfectly understand what happens in second code, but I don't understand behaviour of the first one.


回答1:


In this code:

def hidePasswords(L, password):
    for elem in L:
        if elem == password:
            elem = "*"*len(password)
    return L

In the loop, elem is being set to each value in L. Then you reassign elem to be something different. So it was the value in L, then it is something else. That doesn't affect the value in L, because elem isn't a reference.

You could write this more succinctly as:

def hidePasswords(L, password):
    return ['*'*len(password) if elem==password else elem for elem in L]



回答2:


khelwood has given a good answer (as usual), but I'll just add a few more points.

Thinking about how Python works in terms of concepts from other languages like pass-by-value and pass-by-reference isn't so helpful. Rather than thinking about variables, their contents and pointers to them, try to adopt the Pythonic viewpoint and think in terms of objects being bound to names, and whether or not the objects (and their contents) are mutable or not.

These concepts are not only important in understanding what happens when you call a function in Python, it applies generally, even to simple assignments. In other words, although an assignment statement may look like an assignment statement in other languages, what's really happening is not quite the same.

Stack Overflow regular Ned Batchelder has a great article with cute diagrams on this topic: Facts and myths about Python names and values

Here's a variation on your code that mutates the list passed to it. The usual Python convention is that functions that mutate an object do not return it (although sometimes it's convenient to bend that convention).

#! /usr/bin/env python

def hidePasswords(L, password):
    for i, elem in enumerate(L):
        if elem == password:
            L[i] = "*" * len(password)
    return

words = ["test", "test1", "test8"]
hidePasswords(words, "test")
print(words)

output

['****', 'test1', 'test8']


来源:https://stackoverflow.com/questions/26730378/list-as-a-function-argument-modifications-discarded

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!