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 協議》,轉載必須註明作者和本文連結