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

Python类实例的函数传递机制:传引用还是传值?

Python类实例传递给函数的机制与行为解析

核心本质:Python的参数传递是「传对象引用」

Python里所有变量本质都是对象的引用。当你把变量传给函数时,实际上是把这个引用的副本传给了函数的形参。也就是说,函数内的形参和外部的实参最初指向同一个对象,但形参本身是局部变量——如果给形参重新赋值,只是让这个局部变量指向另一个对象,完全不会影响外部实参的指向。

为什么第一段代码输出dog?

看你这段代码:

def change_animal(animal_1, animal_2):
    animal_1 = None  # 局部变量animal_1改为指向None,和外部的animal_1彻底无关
    animal_1 = animal_2  # 局部变量指向animal_2的对象,外部的animal_1仍指向原来的dog实例

外部的animal_1自始至终都指向最初创建的Animal('dog', 'bark')对象,函数里的操作只是修改了局部变量的指向,所以最后打印结果还是dog。

为什么第二段代码输出duck?

这段代码里你没有给形参animal_1重新赋值,而是直接修改了它指向的对象的属性:

def change_animal(animal_1, animal_2):
    animal_1.name = animal_2.name
    animal_1.sound = animal_2.sound

因为函数内的animal_1和外部的animal_1指向同一个对象,修改对象的属性会直接反映到外部,所以最后打印结果是duck。

避免逐个赋值属性的实用方法

如果你不想手动逐个复制属性,可试试以下几种方案:

1. 利用__dict__批量更新属性

Python对象的自定义属性(未用__slots__限制的)都存在__dict__字典中,直接用update方法就能批量复制:

def change_animal(animal_1, animal_2):
    animal_1.__dict__.update(animal_2.__dict__)

这样能一次性把animal_2的所有属性复制到animal_1,不用逐个写赋值语句。

2. 返回新实例,外部重新赋值

如果不想修改原有对象,而是让外部变量指向新实例,可让函数返回新对象,再在外部重新赋值:

import copy

def change_animal(animal_2):
    # 浅拷贝(如果属性都是不可变类型够用)
    # return Animal(animal_2.name, animal_2.sound)
    # 深拷贝(适合属性包含可变对象的场景)
    return copy.deepcopy(animal_2)

# 外部调用
animal_1 = change_animal(animal_2)

这种方式逻辑更清晰,尤其适合线程等复杂场景,能避免共享对象带来的并发问题。

3. 给类添加复制方法

在Animal类中定义一个复制方法,后续新增属性时只需修改这个方法:

class Animal:
    def __init__(self, name, sound):
        self.name = name
        self.sound = sound
    
    def copy_from(self, other):
        self.name = other.name
        self.sound = other.sound
        # 以后加新属性,只需要在这里追加一行

# 调用时直接调用实例方法
animal_1.copy_from(animal_2)

这种方法比手动逐个赋值更易维护,不用修改所有调用的地方。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 05:35:18