Python按对象引用传递最佳实践:如何避免传参意外副作用
避免Python可变/不可变参数隐式行为问题的最佳实践
以下规则均为可落地、无需额外记忆底层实现细节的强约束,适合作为编码规范传递给学生:
- 严格区分纯函数和副作用函数,两类逻辑禁止混用
纯函数仅通过返回值输出运算结果,绝对不修改任何传入参数或全局状态;副作用函数仅用来修改入参/全局状态,返回值仅允许返回成功/失败状态码类信息,不承载运算结果。 - 纯函数接收可变类型参数(list、dict、numpy数组、自定义类实例等)时,进入函数第一行先做显式拷贝
示例:
无需判断运算符是否生成临时对象,强制拷贝后所有操作均隔离,彻底避免意外副作用。def fun(x: np.ndarray) -> np.ndarray: x = x.copy() # 后续所有操作均在拷贝上执行,完全不会影响外部原对象 x += 1 x = x + 1 return x - 副作用函数内禁止对参数变量做重绑定操作
副作用函数全程仅允许使用+=、append()、fill()等明确的原地操作修改参数,绝对不要出现参数名 = 新值这类给参数变量重新赋值的语句,避免中途变量指向新对象导致后续修改不生效。 - 强制使用类型标注+静态类型检查工具
给所有函数参数、返回值加明确的类型标注,配合mypy、pyright等工具做静态检查。如果参数标注为不可变类型(int、str、tuple等),直接放弃修改该参数的副作用逻辑,统一通过返回值传递新值;如果标注为可变类型,编码前先明确函数是纯函数还是副作用函数。 - 不确定被调用函数是否会修改参数时,调用方主动传拷贝
如果使用第三方/其他人编写的函数,不确定其是否会修改入参,传参时主动传入拷贝,例如fun(var2.copy()),把行为控制权握在自己手里,无需猜测对方实现逻辑。 - 所有涉及可变参数的函数,必须在文档字符串中明确说明是否修改入参
示例:"""
参数x: 输入的numpy数组
行为说明:本函数会原地修改x的值,无有效返回值
"""
无论是自己后续维护还是团队协作,都能直接明确函数行为,无需逐行读代码判断。
内容的提问来源于stack exchange,提问作者marco
相关产品推荐
相关产品推荐

