You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python可变对象按引用传参?为何函数内赋值后外部变量未变

为什么Python函数内给参数赋值后,外部变量没变化?

我来帮你理清这个问题——你遇到的是Python参数传递里一个非常常见的误解,直接给你拆解清楚:

先看你的完整代码(整理后)

import pandas as pd

a = pd.DataFrame(range(3))
b = pd.DataFrame(range(5))

def change(origin, new):
    print(id(origin))
    print(id(new))
    origin = new
    print(id(origin))
    print(id(new))

change(a,b)
# 输出:
# 559599568
# 559251864
# 559251864
# 559251864

print(a)
# 输出:
#    0
# 0  0
# 1  1
# 2  2

print(b)
# 输出:
#    0
# 0  0
# 1  1
# 2  2
# 3  3
# 4  4

print(id(a))  # 559599568L
print(id(b))  # 559251864L

核心原因:Python既不是值传递,也不是引用传递,而是「传对象的引用」

你之前的误解是觉得可变对象是按引用传参,但其实Python的参数传递规则是:把外部变量的对象引用,赋值给函数的局部参数变量。

具体到你的代码:

  1. 调用change(a,b)时,Python把a指向的DataFrame对象的引用,赋值给函数里的origin;把b的引用赋值给new。这时候origin和a指向同一个对象(所以初始id相同),new和b也是如此。
  2. 当你执行origin = new时,你只是修改了**函数内部的局部变量origin**的指向——让它从原来的a的对象,改成指向b的对象。但这个操作完全和外部的a没关系,a还是牢牢指向原来的那个DataFrame。

打个生活化的比方:你和同事手里各有一张纸条,上面写着「会议室A」的地址。你把自己手里的纸条改成「会议室B」,同事手里的纸条还是写着「会议室A」——你们俩的纸条是独立的,只是一开始写的地址一样而已。这里的「纸条」就是变量(a和origin),「地址」就是对象的id。

那如果想让外部的a变成b,该怎么做?

有两种常用方法:

  1. 让函数返回新对象,外部重新赋值
    这是最清晰、最推荐的方式:

    def change(origin, new):
        return new
    
    a = change(a, b)  # 把函数返回的b的引用重新赋值给a
    

    这样操作后,a就会指向b的对象,id也会变成和b一样。

  2. 修改可变对象的内部状态,而不是重新赋值变量
    因为DataFrame是可变对象,你可以直接修改它的内容,而不是让origin指向新对象:

    def change(origin, new):
        origin.clear()  # 清空原来的内容
        origin.append(new, ignore_index=True)  # 把b的内容加进去
    
    change(a, b)
    

    这种方式下,a的id不会变,但它的内容已经变成了b的内容——相当于你没有换纸条,而是直接去会议室A把里面的东西换成了会议室B的。

最后再划个重点

  • Python里的变量都是「对象的引用」,不是对象本身。
  • 函数参数传递是把引用赋值给局部变量,不是传递变量本身的引用。
  • 对函数内的局部参数重新赋值,不会影响外部变量;只有修改可变对象的内部状态,或者外部重新赋值,才能改变外部的结果。

内容的提问来源于stack exchange,提问作者Lisa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:52:20