编程学习网 > 编程语言 > Python > Python 传参是值还是引用?都不是!
2026
11-14

Python 传参是值还是引用?都不是!


同一份数据,传给两个函数,一个改了外面,一个没改。

def f(lst):
    lst.append(1)
def g(lst):
    lst = [1]
data = []
f(data)
print(data)   # [1]
data = []
g(data)
print(data)   # []

都是 lst,为什么一个生效一个不生效?

Python 传的是对象引用,但赋值只是换个名字。

01

先看 id 怎么变

传参时,函数里的形参和外面的实参指向同一个对象。所以在函数里做原地修改,外面能看到。

def f(lst):
    print(id(lst))
data = []
f(data)
print(id(data))   # 两个 id 一样

而 lst = [1] 是重新绑定:它让 lst 这个名字指向一个新对象,原来那个对象没动。外面的 data 还指着旧的。

def g(lst):
    lst = [1]
    print(id(lst))   # 新的 id
data = []
g(data)
print(id(data))       # 还是旧的

02

可变和不可变,表现不一样

列表、字典、set 这类可变对象,原地修改会穿透到外部,看起来像「引用传递」。

整数、字符串、元组这类不可变对象,任何「修改」都会新建对象、重新绑定,看起来又像「值传递」。

def add_one(n):
    n += 1
x = 10
add_one(x)
print(x)   # 10,没变

所以「值传递还是引用传递」这个问题本身问错了。准确说法是:传递对象引用,赋值改变绑定。

03

实际写代码时的三条建议

第一,函数默认不要原地修改传进来的参数,除非函数名明确说了会改,比如 sort()。

第二,需要修改就返回新对象,让调用方自己决定要不要接。sorted() 就是这么设计的。

第三,参数默认值别放可变对象,这就是 A01 那个坑的同一个根源。

函数里的操作

外部是否受影响

原因

lst.append(x)

是

原地修改同一个对象

lst[0] = x

是

原地修改

lst = [x]

否

重新绑定,新对象

n += 1(int)

否

不可变,必然新建

d.update(...)

是

原地修改

传的是引用,改的是对象。

赋值只改名字,不改别人。

搞清楚这一层,很多「为什么函数改了我的数据」的疑问会一起消失。

以上就是“Python 传参是值还是引用?都不是!”的详细内容,想要了解更多Python教程欢迎持续关注编程学习网。 

扫码二维码 获取免费视频学习资料

Python编程学习

查 看2022高级编程视频教程免费获取