如何通过引用传递函数来更改列表?

时间:2016-09-17 14:55:25

标签: python list

代码传递给一个数组。我的理解是这个传递是通过引用完成的。我希望函数递归地将列表的最后剩余的一半分成两部分,并将它被拆分的每个值设置为零。 零更改发生在数组中,但是当我在最后调用print a时,我得到了原始数组。

我做错了什么?

a = range(10)

def listreduction(array):
    if len(array) == 1:
        array[0] = 0
        return

    split = len(array)/2
    array[split] = 0

    return listreduction(array[split:])

listreduction(a)
print a

当前输出

[0, 1, 2, 3, 4, 0, 6, 7, 8, 9]

第二个的右边应该是更多的零

4 个答案:

答案 0 :(得分:2)

切片会创建一个新列表。如果你想以递归方式执行此操作,则必须传递函数应该在列表上工作的索引,而不是实际的切片。

答案 1 :(得分:1)

由于您使用递归,因此参数中的切片操作将创建与您的实例不同的新列表实例。这就是原因。

您可以按以下方式更改代码:

a = range(10)

def list_reduction(array, position=0):
    if len(array) -1 <= position:
        return

    split = position + (len(array) - position) / 2
    array[split] = 0
    return list_reduction(array, split)

list_reduction(a)
print a

输出结果为:

[0, 1, 2, 3, 4, 0, 6, 0, 0, 0]

答案 2 :(得分:1)

这可能是你想要的。

a = range(1, 10)

def list_reduction(l, prev_split_pos=None):
    split_pos = (len(l) + prev_split_pos) / 2 if prev_split_pos else len(l) / 2
    if split_pos == prev_split_pos:
        return
    l[split_pos] = 0
    return list_reduction(l, split_pos)

list_reduction(a)
print a

那么,对你的代码。每次执行列表切片时,实际上都会生成一个新列表,该列表与旧列表完全没有关联。这就是为什么除了第一个之外你没有看到任何突变的原因。

答案 3 :(得分:1)

在Python中,argumnet传递与其他传统编程语言不同。参数由对象引用传递。以及是否修改引用的对象取决于两件事

  • 变量是可变的还是不可变的。在您的情况下,range将创建一个列表,以便它是一个可变对象。这意味着,如果您更新array,则还应更新a
  • 操作。 =操作将始终创建新的对象引用。所以即使你的情况array是可变的,但是因为你正在进行赋值操作它将创建一个新的对象引用。

以下示例应该为您清理一些事情。

示例1

  >>> a = [1,2]
    def fun1(array):
        array= array + [3]
        print "var array = %s" %array

    fun1(a)
    print "var a = %s" %a

<强>输出

var array = [1, 2, 3]
var a = [1, 2]

示例2

a = [1,2]
def fun1(array):
    array.append(3)
    print "var array = %s" %array

fun1(a)
print "var a = %s" %a

<强>输出

var array = [1, 2, 3]
var a = [1, 2,3]