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

Groovy与Python函数参数传值传引用区分及堆栈分配规则疑问

结论先行

你的核心猜测(Groovy、Python本质全是按值传递)是对的,但你把现象归因于「栈/堆分配差异」是错的,这个和内存存储位置没有关系,是语言的传参语义+对象可变性共同导致的差异。

核心语义解释

Groovy(基于JVM)和Python的参数传递统一遵循**按对象引用传值(也叫传共享pass-by-sharing)**规则,属于纯按值传递的一种实现:

  • 这两门语言中所有变量本质都是「对象的引用」,不存在C语言中直接存储值的栈变量
  • 函数传参时,永远会把实参的引用值拷贝一份传给形参,形参和实参是两个独立的引用,指向同一个对象
  • 两门语言都不支持真正的按引用传递:你无法通过修改函数形参的指向来改变外部实参的指向,这也是你给形参重新赋值不会影响外部变量的根本原因。

你的代码运行结果的原因

字典修改外部可见的原因

你调用dfunc(my_dict)时:

  1. 形参v和外部的my_dict是两个独立的引用,指向同一个字典对象
  2. 执行v.foo = "dolor"时,你是通过引用修改了指向的对象本身的内容,所以外部的my_dict指向同一个对象,自然能看到修改
  3. 后续执行v = [a:"a", b:"b"]时,你只是修改了形参v这个引用本身的指向,让它指向了一个新的字典对象,完全不会影响外部my_dict的指向,所以外部的my_dict还是原来的对象,只是属性被修改了

整数修改外部不可见的原因

你调用podfunc(my_int)时:

  1. 整数是不可变对象,语言层面不允许修改整数对象本身的内容
  2. 执行v = 42时,你只是把形参v的引用指向了新的整数对象42,完全碰不到外部my_int的引用,所以外部的my_int还是指向原来的5

关于栈堆分配的疑问

栈/堆分配是语言运行时的底层实现细节,和上层的传参语义没有绑定关系:

  • Groovy、Python都是托管运行的语言,内存分配由运行时自动管理,开发者不需要、也没有语法可以直接控制变量的存储位置
  • 即使是对象类型,只要满足运行时的优化条件(比如JVM的逃逸分析判定对象没有逃出当前作用域),也可能被分配在栈上,完全不会影响上层的传参表现
  • 你看到的两个def声明没有差异,是因为这两门语言的语法层面本来就没有暴露栈分配的相关概念,所有变量都是对象引用,存储位置完全由运行时动态决定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 00:57:01