python的赋值传递
python 的参数传递是赋值传递,或者称为对象的引用传递;既不是值传递,也不是引用传递。「“Call by Object Reference” or “Call by assignment”.」
引用 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 中的数据类型大致分为 2 类:
- 不可变:数值、字符串、元组
- 可变:列表、字典、集合
给出一个 demo:
def f_list(i: list):
print("list id init:", id(i))
print("list:", i)
i += [2]
print("list id:", id(i))
def f_dict(n: dict):
print("dict id init:", id(n))
print("dict:", n)
n |= {"c": "d"}
print("dict id:", id(n))
def f_int(m: int):
print("int id init:", id(m))
print("int:", m)
m += 1
print("int id:", id(m))
def f_str(o: str):
print("str id init:", id(p))
print("str:", o)
o += "o"
print("str id:", id(o))
if __name__ == '__main__':
i = [0]
print("list id init:", id(i))
f_list(i)
print(f"list: {i}\n")
n = {"a": "b"}
print("dict id init:", id(n))
f_dict(n)
print(f"dict: {n}\n")
m = 1
print("int id init:", id(m))
f_int(m)
print(f"int: {m}\n")
p = "k"
print("str id init:", id(p))
f_str(p)
print(f"str: {p}\n")
我们看一下输出:
list id init: 4545683712
list id init: 4545683712
list: [0]
list id: 4545683712
list: [0, 2]
dict id init: 4544160960
dict id init: 4544160960
dict: {'a': 'b'}
dict id: 4544160960
dict: {'a': 'b', 'c': 'd'}
int id init: 4543166768
int id init: 4543166768
int: 1
int id: 4543166800
int: 1
str id init: 4544020656
str id init: 4544020656
str: k
str id: 4545737008
str: k
我们通过观察 id 可以看到:
- 以 list 和 dict 为代表的可变数据结构的数据类型在函数处理后,原变量的值发生了变化;
- 以 str 和 int 为代表的不可变数据结构的数据类型在函数处理后,原变量的值保持不变。
这也可以证明了 python 既不是值传递,否则同一个值的内存 id 不应该是一样的;也不是引用传递,因为字符串和数值在函数处理后,id 发生了变化,但值本身并没有发生改变。
所以总之,Python 中参数的传递既不是值传递,也不是引用传递,而是赋值传递,或者是叫对象的引用传递。
一些参考链接:
Tips: 如有不当之处,请指正。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: