Python的call by object reference概念可视化及核心原理问询
Python的「按赋值传参」与对象-名称关系可视化解析
先掰正核心认知:对象没有「名称」,只有「指向对象的名称」
你听到的「Python对象没有名称」不是敷衍,是本质——Python里的变量(名称)和对象完全是两回事:
- 对象是内存里实实在在存数据的实体(比如整数5、字符串"hello"、列表[1,2,3]),它本身没有名字,就像你包里的笔记本,本子上不会刻着你的名字。
- 名称(变量)是你给这个对象贴的「指向标签」,就像你在包的外侧写「我的笔记本」——这个标签和本子是分离的,你可以把标签撕下来贴到另一本本子上,也可以给同一个本子贴多个标签。
用文字可视化这个绑定过程:
- 执行
x = 5:内存里先生成一个值为5的整数对象(假设内存地址是0x123),然后把名称x和0x123绑定,相当于x→0x123(值5)。 - 执行
y = x:不是复制5这个对象,而是把名称y也绑定到0x123,变成x→0x123,y→0x123,两个名称指向同一个对象。 - 执行
x = 10:生成新的整数对象0x456(值10),把x的绑定改成x→0x456,但y还是指向0x123,所以y的值还是5。
不可变对象传参的本质:为什么看起来像「传值」?
Python的函数传参规则叫按赋值传参(Call by Assignment),本质就是执行「形参 = 实参」这个操作——把实参当前的绑定关系复制给形参。
拿不可变对象(数字、字符串、元组)举例:
def change_num(a): a = 20 # 这里不是修改原来的10,而是让a绑定新的整数对象20 num = 10 change_num(num) print(num) # 输出10
可视化这个传参过程:
- 调用
change_num(num)时,形参a被赋值为num的绑定,也就是a→0x789(值10)。 - 函数里执行
a=20,生成新对象0xabc(值20),把a的绑定改成a→0xabc。 - 但实参
num的绑定还是num→0x789,所以外部的num不受影响,看起来像「传值」,但本质是不可变对象无法被修改,只能重新绑定新对象。
如果是可变对象(列表、字典),就能修改对象本身:
def add_item(lst): lst.append(4) # 直接修改lst指向的那个列表对象 my_list = [1,2,3] add_item(my_list) print(my_list) # 输出[1,2,3,4]
这里形参lst和实参my_list指向同一个列表对象,修改对象的内容会影响所有指向它的名称,因为对象本身变了。
对比你提到的文件类比:差异在哪里?
硬盘上的文件名和文件是强关联的——文件名是文件的标识(快捷方式本质也是指向文件的链接),删除文件名后文件可能还在,但文件名和文件是绑定的。
但Python的名称和对象是弱绑定:
- 一个对象可以被多个名称指向(比如
x = [1,2]; y = x)。 - 一个名称可以随时切换指向不同的对象(
x = 5; x = "hello")。 - 对象可以没有任何名称(比如执行
del x后,如果没有其他名称指向0x123,这个对象会被Python的垃圾回收机制销毁)。
总结核心机制
- 对象是数据载体:存在内存中,本身无名称,分为可变(可修改内容)和不可变(内容不可改,只能生成新对象)两类。
- 名称是绑定关系:变量名只是指向对象的「指针标签」,和对象完全分离。
- 传参是复制绑定:函数传参就是把实参的绑定复制给形参,形参和实参初始指向同一个对象;如果是不可变对象,修改形参只是切换绑定,不影响实参;如果是可变对象,修改对象内容会影响所有指向它的名称。
内容的提问来源于stack exchange,提问作者Swawa
相关产品推荐
相关产品推荐

