(原创)一个示例程序告诉你,Python参数传递的真相:是值传递还是引用传递?

其实,作为一切皆对象的Python, 所有的参数都是引用传递。
但是,对于那些不可改变的对象,如常量、tuple等不可改变序列,
他们作为实参传递后,因为改变不了,所以不会被函数改变。
而可改变序列、自定义类对象,可以改变其属性值。
但是函数内如果给形参整体赋新值,是不会改变主程序传入的实参的,
因为,函数内把形参指向了新的对象,而不是实参代表的原对象。

示例程序如下:

# encoding:utf-8


def para(number_1, char_1, string_1, tuple_1, list_1, dict_1, obj_1):
    print("para 得到的参数值:")
    print("para number_1 = ", number_1)
    print("para string_1 = ", string_1)
    print("para char_1 = ", char_1)
    print("para tuple_1 = ", tuple_1)
    print("para list1_1 = ", list_1)
    print("para dict_1 = ", dict_1)
    print("para obj_1 = ", obj_1)
    print("现在对每一个参数都重新赋值")
    number_1 = 2
    char_1 = 'b'
    string_1 = "string b."
    tuple_1 = (2, 'b')
    list_1 = [2, 'b']
    dict_1 = {'b': 2, 'c': 3}
    obj_1 = User('Carlan', 33, '333333')


def para2(list_1, dict_1, obj_1):
    print("para2中对可变类型参数的属性值进行改变:")
    list_1[0] = 3
    list_1[1] = 'c'
    list_1.append('$')
    dict_1['a'] = 1000
    dict_1['b'] = 2000
    dict_1['c'] = 3000
    obj_1.name = 'Britan'
    obj_1.years = 22
    obj_1.id = '222222'


class User():
    def __init__(self, name, years, id):
        self.name = name
        self.years = years
        self.id = id

    def __repr__(self):
        return str((self.name, self.years, self.id))

    def __str__(self):
        return self.__repr__()


if __name__ == "__main__":
    number_01 = 1
    char_01 = 'a'
    string_01 = 'string a'
    tuple_01 = (1, 'a')
    list_01 = [1, 'a']
    dict_01 = {'a': 1, 'z': 26}
    obj_01 = User('Alice', 11, '11111')
    print("从主程序将数据作为参数向函数para传递. ")
    para(number_01, char_01, string_01, tuple_01, list_01, dict_01, obj_01)
    print("在函数para对参数修改以后,主程序中各个参数的值:")
    print("main number_01 = ", number_01, " #不变")
    print("main string_01 = ", string_01, " #不变")
    print("main char_01 = ", char_01, " #不变")
    print("main tuple_01 = ", tuple_01, " #不变")
    print("main list1_01 = ", list_01, " #不变")
    print("main dict_01 = ", dict_01, " #不变")
    print("main obj_01 = ", obj_01, " #不变")
    print("\n从主程序将可变数据类型作为参数向函数para2传递. ")
    para2(list_01, dict_01, obj_01)
    print("在函数para2对参数修改以后,主程序中各个参数的值:")
    print("main list1_01 = ", list_01, " #变")
    print("main dict_01 = ", dict_01, " #变")
    print("main obj_01 = ", obj_01, " #变")

    print("\n\n====以下是在主程序中直接进行数据传递和改动=====:")
    print("原始变量恢复初始值:")
    number_01 = 1
    char_01 = 'a'
    string_01 = 'string a'
    tuple_01 = (1, 'a')
    list_01 = [1, 'a']
    dict_01 = {'a': 1, 'z': 26}
    obj_01 = User('Alice', 11, '11111')

    number_03 = number_01
    char_03 = char_01
    string_03 = string_01
    tuple_03 = tuple_01
    list_03 = list_01
    dict_03 = dict_01
    obj_03 = obj_01

    print("接收值=原始值:")
    print("rec number_03 = ", number_03)
    print("rec string_03 = ", string_03)
    print("rec char_03 = ", char_03)
    print("rec tuple_03 = ", tuple_03)
    print("rec list1_03 = ", list_03)
    print("rec dict_03 = ", dict_03)
    print("rec obj_03 = ", obj_03)

    print("接收变量直接改变值后双方的值:")
    numcer_03 = 3
    char_03 = 'c'
    string_03 = "string c."
    tuple_03 = (3, 'c')
    list_03 = [3, 'c']
    dict_03 = {'c': 3, 'c0': 30}
    ocj_03 = User('Carlan', 33, '333333')

    print("在接收变量对变量值修改以后,原始值全都不变")
    print("orginal number_01 = ", number_01)
    print("orginal string_01 = ", string_01)
    print("orginal char_01 = ", char_01)
    print("orginal tuple_01 = ", tuple_01)
    print("orginal list1_01 = ", list_01)
    print("orginal dict_01 = ", dict_01)
    print("orginal obj_01 = ", obj_01)

    print("\n接收后, 可变数据类型改变自己的属性值")
    list_04 = list_01
    dict_04 = dict_01
    obj_04 = obj_01
    
    list_04[0] = 3
    list_04[1] = 'c'
    list_04.append('$')
    dict_04['a'] = 1000
    dict_04['b'] = 2000
    dict_04['c'] = 3000
    obj_04.name = 'Britan'
    obj_04.years = 22
    obj_04.id = '222222'
    
    print("可变接收变量改变对象中元素的值后,原始值随之改变")
    print("orginal list1_01 = ", list_01)
    print("orginal dict_01 = ", dict_01)
    print("orginal obj_01 = ", obj_01)

    print("\n结论:所有的参数传递都是引用传递。\n",
          "参数传递值的变化规律和同一程序中数据传递值的变化规律完全相同。\n",
          "即:由于是引用,2个指向同一对象的可变类型的属性值一同改变,\n"
          "所有类型(无论是否可变)重新赋值都等于指向新的对象,原引用变量的值不变。")

 

 

执行结果如下:

C:\PythonProjectSpace\foom\Scripts\python.exe D:/python_work/mogui/param.py
从主程序将数据作为参数向函数para传递. 
para 得到的参数值:
para number_1 =  1
para string_1 =  string a
para char_1 =  a
para tuple_1 =  (1, 'a')
para list1_1 =  [1, 'a']
para dict_1 =  {'a': 1, 'z': 26}
para obj_1 =  ('Alice', 11, '11111')
现在对每一个参数都重新赋值
在函数para对参数修改以后,主程序中各个参数的值:
main number_01 =  1  #不变
main string_01 =  string a  #不变
main char_01 =  a  #不变
main tuple_01 =  (1, 'a')  #不变
main list1_01 =  [1, 'a']  #不变
main dict_01 =  {'a': 1, 'z': 26}  #不变
main obj_01 =  ('Alice', 11, '11111')  #不变

从主程序将可变数据类型作为参数向函数para2传递. 
para2中对可变类型参数的属性值进行改变:
在函数para2对参数修改以后,主程序中各个参数的值:
main list1_01 =  [3, 'c', '$']  #变
main dict_01 =  {'a': 1000, 'z': 26, 'b': 2000, 'c': 3000}  #变
main obj_01 =  ('Britan', 22, '222222')  #变


====以下是在主程序中直接进行数据传递和改动=====:
原始变量恢复初始值:
接收值=原始值:
rec number_03 =  1
rec string_03 =  string a
rec char_03 =  a
rec tuple_03 =  (1, 'a')
rec list1_03 =  [1, 'a']
rec dict_03 =  {'a': 1, 'z': 26}
rec obj_03 =  ('Alice', 11, '11111')
接收变量直接改变值后双方的值:
在接收变量对变量值修改以后,原始值全都不变
orginal number_01 =  1
orginal string_01 =  string a
orginal char_01 =  a
orginal tuple_01 =  (1, 'a')
orginal list1_01 =  [1, 'a']
orginal dict_01 =  {'a': 1, 'z': 26}
orginal obj_01 =  ('Alice', 11, '11111')

接收后, 可变数据类型改变自己的属性值
可变接收变量改变对象中元素的值后,原始值随之改变
orginal list1_01 =  [3, 'c', '$']
orginal dict_01 =  {'a': 1000, 'z': 26, 'b': 2000, 'c': 3000}
orginal obj_01 =  ('Britan', 22, '222222')

结论:所有的参数传递都是引用传递。
 参数传递值的变化规律和同一程序中数据传递值的变化规律完全相同。
 即:由于是引用,2个指向同一对象的可变类型的属性值一同改变,
所有类型(无论是否可变)重新赋值都等于指向新的对象,原引用变量的值不变。

Process finished with exit code 0
 

 

 

  • 1
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

原石化玉

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值