14、Python面试题解析:Python是按引用调用还是按值调用

1. Python 的参数传递机制

Python 的参数传递机制既不是纯粹的按值调用(Call by Value),也不是纯粹的按引用调用(Call by Reference),而是一种称为按对象引用调用(Call by Object Reference)或按共享传递(Pass by Sharing)的机制。

核心概念
  • 不可变对象(如整数、字符串、元组):在函数内部修改时,会创建一个新的对象,原始对象不受影响。
  • 可变对象(如列表、字典、集合):在函数内部修改时,会直接修改原始对象。

2. 不可变对象的传递

不可变对象(如整数、字符串、元组)在函数内部修改时,会创建一个新的对象,原始对象不受影响。

示例 1:整数(不可变对象)
def modify_number(x):
    print("Inside function (before modification):", x, id(x))
    x = x + 10  # 创建一个新的整数对象
    print("Inside function (after modification):", x, id(x))

num = 5
print("Outside function (before call):", num, id(num))
modify_number(num)
print("Outside function (after call):", num, id(num))

输出

Outside function (before call): 5 140736784037568
Inside function (before modification): 5 140736784037568
Inside function (after modification): 15 140736784037888
Outside function (after call): 5 140736784037568

解释

  • 在函数内部修改 x 时,会创建一个新的整数对象,原始对象 num 不受影响。
  • id(x) 在修改前后发生了变化,说明 x 指向了一个新的对象。
示例 2:字符串(不可变对象)
def modify_string(s):
    print("Inside function (before modification):", s, id(s))
    s = s + " World"  # 创建一个新的字符串对象
    print("Inside function (after modification):", s, id(s))

text = "Hello"
print("Outside function (before call):", text, id(text))
modify_string(text)
print("Outside function (after call):", text, id(text))

输出

Outside function (before call): Hello 140736784037568
Inside function (before modification): Hello 140736784037568
Inside function (after modification): Hello World 140736784037888
Outside function (after call): Hello 140736784037568

解释

  • 在函数内部修改 s 时,会创建一个新的字符串对象,原始对象 text 不受影响。
  • id(s) 在修改前后发生了变化,说明 s 指向了一个新的对象。

3. 可变对象的传递

可变对象(如列表、字典、集合)在函数内部修改时,会直接修改原始对象。

示例 3:列表(可变对象)
def modify_list(lst):
    print("Inside function (before modification):", lst, id(lst))
    lst.append(4)  # 直接修改原始对象
    print("Inside function (after modification):", lst, id(lst))

my_list = [1, 2, 3]
print("Outside function (before call):", my_list, id(my_list))
modify_list(my_list)
print("Outside function (after call):", my_list, id(my_list))

输出

Outside function (before call): [1, 2, 3] 140736784037568
Inside function (before modification): [1, 2, 3] 140736784037568
Inside function (after modification): [1, 2, 3, 4] 140736784037568
Outside function (after call): [1, 2, 3, 4] 140736784037568

解释

  • 在函数内部修改 lst 时,直接修改了原始对象 my_list
  • id(lst) 在修改前后没有变化,说明 lst 仍然指向同一个对象。
示例 4:字典(可变对象)
def modify_dict(d):
    print("Inside function (before modification):", d, id(d))
    d["new_key"] = "new_value"  # 直接修改原始对象
    print("Inside function (after modification):", d, id(d))

my_dict = {"key": "value"}
print("Outside function (before call):", my_dict, id(my_dict))
modify_dict(my_dict)
print("Outside function (after call):", my_dict, id(my_dict))

输出

Outside function (before call): {'key': 'value'} 140736784037568
Inside function (before modification): {'key': 'value'} 140736784037568
Inside function (after modification): {'key': 'value', 'new_key': 'new_value'} 140736784037568
Outside function (after call): {'key': 'value', 'new_key': 'new_value'} 140736784037568

解释

  • 在函数内部修改 d 时,直接修改了原始对象 my_dict
  • id(d) 在修改前后没有变化,说明 d 仍然指向同一个对象。

4. 重新赋值与修改的区别

  • 重新赋值:会创建一个新的对象,原始对象不受影响。
  • 修改:会直接修改原始对象。
示例 5:重新赋值 vs 修改
def reassign_list(lst):
    lst = [4, 5, 6]  # 重新赋值,创建一个新的列表对象
    print("Inside function (after reassignment):", lst, id(lst))

def modify_list(lst):
    lst.append(4)  # 修改原始列表对象
    print("Inside function (after modification):", lst, id(lst))

my_list = [1, 2, 3]
print("Outside function (before call):", my_list, id(my_list))
reassign_list(my_list)
print("Outside function (after reassignment):", my_list, id(my_list))

modify_list(my_list)
print("Outside function (after modification):", my_list, id(my_list))

输出

Outside function (before call): [1, 2, 3] 140736784037568
Inside function (after reassignment): [4, 5, 6] 140736784037888
Outside function (after reassignment): [1, 2, 3] 140736784037568
Inside function (after modification): [1, 2, 3, 4] 140736784037568
Outside function (after modification): [1, 2, 3, 4] 140736784037568

解释

  • reassign_list 中重新赋值 lst,创建了一个新的列表对象,原始对象 my_list 不受影响。
  • modify_list 中修改 lst,直接修改了原始对象 my_list

5. 总结

Python 的参数传递机制是按对象引用调用(Call by Object Reference)或按共享传递(Pass by Sharing)。具体表现为:

  • 不可变对象:在函数内部修改时,会创建一个新的对象,原始对象不受影响。
  • 可变对象:在函数内部修改时,会直接修改原始对象。

通过理解这一机制,可以更好地掌握 Python 中函数参数传递的行为,避免常见的错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值