是时候回顾一下Python的函数传参方式了。python
Python的传参方式既不是pass-by-value(传值),也不是pass-by-reference(传引用),而是pass-by-object。app
Python中每一个object都有"type", 和“identifier”:ide
# int 3 id(3) # this get the identifier type(3) # this get the type
也有本身的name -- 但object并不知道本身被叫作什么;一个object能够被叫作不少不一样的名字:函数
a = 1 b = 1 # object int 1 is called a, and also b
上面的行为先将1
这个整型命名为a
,将a
加入当前的namespace中,而后又将1
再次命名为b
,将b
加入当前的namespace中。this
a = 1 a = 2
上面先将1
命名为a
,将a
加入当前的namespace中,又将2
命名为a
,替换了以前a
所指向的object。在整个过程当中,只是name的指向发生了变化,namespace发生了变化,而object没有发生变化。spa
Python的object分红mutable(可变)和immutable(不可变)。可变的object好比字典(dict
), 列表(list
);不可变的好比元组(tuple
),固定字符串(string
),整形,长整形,浮点数....code
def func(a): # do something on a return
当你使用a = 3; func(a)
的时候,所传入的并非a
这个name,而是a
所指向的object: int 3
。htm
a = 3 def func(a): a = 4 return print(a) # 3
由于int 3
不是一个mutable的object,所以在func()
中所作的只是在其namespace中将name a
指向了object: int 4
. 这个改变并不影响func()
之外的namespace.对象
然而,若是传入一个mutable的object,好比一个列表:字符串
a = [] def func(a): a.append(1) return print(a) # [1]
在func()
中a所指向的object发生了改动,所以当函数返回时,以外的namespace中a
所指向的object也发生了改动。
另外,
a = [1, 2, 3] def func(a): a = [] return print(a) # [1, 2, 3]
这种用直接赋值方式改变mutable对象是无效的。须要使用object自带的各类method,好比列表的.append
;a[0] = 1
中a[0]其实也是method的语法糖而已。
https://stackoverflow.com/questions/13299427/python-functions-call-by-reference
http://effbot.org/zone/call-by-object.htm
http://effbot.org/zone/python-objects.htm