Python变量与参数传递

Python变量

变量的赋值,只是表示让变量指向了某个对象,并不表示拷贝对象给变量;而一个对象,可以被多个变量所指向。

a = 1
b = a
a = a + 1 # a = 2, b = 1

可变对象(列表,字典,集合等等)的改变,会影响所有指向该对象的变量。

a = [1, 2, 3]
b = a
a[0] = 0
print b  # [0, 2, 3]

对于不可变对象(字符串,整型,元祖等等),所有指向该对象的变量的值总是一样的,也不会改变。 但是通过某些操作(+= 等等)更新不可变对象的值时,会返回一个新的对象。

a = '1'
b = '1'

id(a)  # 4467286984
id(b)  # 4467286984

c = a + b
id(c)  # 4455971336 返回了新的对象

变量可以被删除,但是对象无法被删除。

l = [1, 2, 3]
del l

值传递 or 引用传递

其他语言不同的是,Python 中参数的传递既不是值传递,也不是引用传递,而是赋值传递,或者是叫对象的引用传递

“Remember that arguments are passed by assignment in Python. Since assignment just creates references to objects, there’s no alias between an argument name in the caller and callee, and so no call-by-reference per Se.”

Python 的参数传递是赋值传递(pass by assignment),或者叫作对象的引用传递(pass by object reference)。

Python 里所有的数据类型都是对象,所以参数传递时,只是让新变量与原变量指向相同的对象而已,并不存在值传递或是引用传递一说。

用函数来改变变量的值

如果你想通过一个函数来改变某个变量的值,通常有两种方法。

一种是创建一个新变量,来保存修改后的值,然后将其返回给原变量。

arg = 1

def change_arg_val(arg):
    new_val = arg + 1
    return new_val

arg = change_arg_val(arg)

这里arg不是指向一个具体的地址,而是一个具体的对象,当new_val = arg + 1执行,new_val就指向了一个新的对象。

第二种是直接将可变数据类型(比如列表,字典,集合)当作参数传入,直接在其上修改;

def change_arg_val(arg):
    arg[0] += 1

arg = [1]
change_arg_val(arg)

在实际工作中,我们更倾向于使用前者;逻辑更清晰,减少耦合,不容易出错。