Python中delete_head1与delete_head2函数差异及变量绑定原理问询
Python列表函数修改差异的原理解析
我们来看以下两个Python函数:
def delete_head1(t): #t[:] = t[1:] t = t[1:]
def delete_head2(t): t[:] = t[1:] #t = t[1:]
执行下面的代码会得到完全不同的结果:
测试1:
k=[1,2,3] delete_head1(k) print(k) # 输出 [1,2,3]
测试2:
k=[1,2,3] delete_head2(k) print(k) # 输出 [2,3]
为什么第二个函数能修改输入的列表,第一个却不行?核心疑问点包括:
- 第一个函数里的
t变成了局部变量,为什么第二个函数的t没有? - 执行
t = t[1:]时,解释器能识别等号后的t,却把等号前的t当成新局部变量?而t[:] = t[1:]时,两个t都指向原列表?Python背后的规则是什么?
核心区别:变量赋值 vs 原地修改对象
Python里的变量本质是对象的引用,函数参数传递的也是这个引用。我们拆解两个函数的执行逻辑:
1. delete_head1的执行过程
- 函数调用时,局部变量
t一开始和外部的k指向同一个列表对象[1,2,3]。 - 当执行
t = t[1:]时,t[1:]会生成一个新的列表切片[2,3],赋值操作=会把局部变量t重新绑定到这个新列表上。 - 此时外部的
k依然指向原来的[1,2,3],所以打印k不会有变化。这里的t确实变成了函数内部的局部变量,因为它的引用指向已经被替换,和原参数解绑了。
2. delete_head2的执行过程
- 同样,局部变量
t一开始指向外部k对应的列表[1,2,3]。 - 执行
t[:] = t[1:]时,这不是变量赋值,而是切片赋值操作——它直接修改t指向的原列表对象:把原列表的所有元素替换成t[1:]的内容(也就是[2,3])。 - 这个操作没有改变
t的引用指向,只是修改了它指向的对象本身。因为外部的k和t指向同一个对象,所以打印k时会看到修改后的结果。
关于变量识别的疑问解答
- 对于
t = t[1:]:等号右边的t是函数参数传入的原引用(指向原列表),但等号左边的t在赋值操作时,会被Python标记为局部变量——只要在函数内部对变量进行赋值,Python就会认为这是一个新的局部变量,和原来的参数引用解绑。 - 对于
t[:] = t[1:]:这里的两个t都是指向原列表的引用。切片赋值是调用列表对象的原地修改方法,本质是对t指向的对象进行操作,没有改变t本身的引用,所以t始终是函数参数传入的那个引用,不会变成新的局部变量。
Python的核心原则
Python遵循**“变量是对象的引用”**的核心规则:
- 赋值语句(
=)的作用是改变变量的引用指向,让变量指向另一个对象。 - 原地操作(比如切片赋值、
append()、pop()等)的作用是修改变量指向的对象本身,不会改变变量的引用。
内容的提问来源于stack exchange,提问作者onyourmark
相关产品推荐
相关产品推荐

