传参不规范,亲人两行泪

Python中的参数传递并非传值也非传引用,传的是对象的引用。

这是一个结论,如果想要知道更多的细节,请阅读《编写高质量代码:改善Python程序的91个建议》的第31条建议。

在Python里面,我们接触到的所有数据类型都是对象,包括常数和字符串。

假设有下面代码:

a = 'ichxx'
def foo(x):
    x = x[::-1]
    print(x)

foo(a)
print(a)

当a传递给x时,它对应的内存模型是这样的

当切片时,产生了新的字符串,此时内存模型变为:

现在,a与x就没有关联了,自然对x的更改就不会反馈到a了

那么,什么样的改变会反馈到实参呢?

在函数中,对可变对象的修改会反馈到对象本身,而对不可变对象的修改则不会

可以把变量名理解成标签,对象理解成商品,我们通过标签去寻找商品。当可变对象修改时,我们通过标签寻找的东西也就相应改变。而不可变对象不可变,所以我们只能把标签撕下来贴到别的商品上面,这样我们也能实现“改变寻找到的东西”的目的,但原来的商品有没有变呢?没有。

最后附上引起我思考这个问题的一段代码(最短寻道算法的实现)

def SCAN(arr=None):
    if not arr:
        raise NoArrayError

    new_arr = sorted(arr)  # 原先是写arr.sort(),这样会改变原来的arr,而arr是全局共用的。这会导致别的调度算法测试时的序列改变。 
    pos = 0
    movement = 0
    if cur < new_arr[0]:
        new_arr.append(0, cur)
        FCFS(new_arr)
    elif cur > new_arr[-1]:
        new_arr.append(cur)
        FCFS(new_arr[::-1])
    else:
        for i in range(len(new_arr)-1):
            if new_arr[i] < cur < new_arr[i+1]:
                pos = i+1
                movement = abs(cur - new_arr[i+1])
                break
    movement += sum([abs(x-y) for x, y in zip(new_arr[pos:-1], new_arr[pos+1:])])
    movement += abs(new_arr[-1] - new_arr[pos-1])
    movement += sum([abs(x-y) for x, y in zip(new_arr[:pos-1], new_arr[1:pos])])
    return movement