如何正确地将参数传递给函数

时间:2016-01-08 02:51:56

标签: python python-3.x parameter-passing

我来自C ++背景,所以这个问题对我来说似乎有点荒谬: 我们假设我有一个功能:

def scale(data, factor):
    for val in data:
        val *= factor

这不按预期工作,如果我传递一个列表,它什么都没改变,但是

def scale(data, factor):
    for index, val in enumerate(data):
        data[index] *= factor

lst = [val * factor for val in lst]正常运行。 Python如何处理参数传递?我怎么知道实际的引用或别名是否通过了?

3 个答案:

答案 0 :(得分:4)

如果要改变列表,则需要引用元素。此版本使用map(可以使用列表推导编写)

def scale(data, factor):
    return map(lambda x : x*factor, data)

lambda函数是anonymous函数。

>>> (lambda x : x + 1) (5)
6

在这种情况下,x取代了变量5 + 1

因此,在这种情况下,我们遍历将函数f(x) -> x * factor应用于列表的每个元素的列表。原始列表没有变异,而是我们返回一个新版本。

答案 1 :(得分:3)

在python中,基本数据类型按值传递 - 例如intstrbool等按值传递

classesenumlistdict等派生数据类型通过引用传递。

在您的示例中,问题是您如何使用for循环 - 而不是函数参数。如果你这样做:

for val in lst:
    val += 1

lst内的值不会更新,因为vallst[0]lst[1]不同,依此类推val是基本的数据类型。因此,即使在这里,val也会按值复制。

其次,在enumerate的示例中:
但是,当您遍历enumerated列表时,您正在使用data[index] - 它会修改实际列表中的元素。

最后,在您使用生成器的示例中:

lst = [val * factor for val in lst] - 此处生成器遍历每个元素并创建一个新列表,该列表再次存储在lst中。这类似a = a + 2,但扩展到列表。

答案 2 :(得分:1)

这种行为是因为基本数据类型是按值传递的,而像列表这样的派生数据类型是通过引用传递的,请考虑这个

>>> x = 24

>>> x + 1
25

>>> x
24

但另一方面有一个列表

>>> y = [1, 2, 3, 4]

>>> y.remove(2)

>>> y
[1,3,4]

因此,在基本数据类型的情况下,在对它们执行操作时应始终小心重新分配值,并且还要小​​心通过引用传递的数据类型,因为您可能在不知道的情况下意外修改变量