其实,作为一切皆对象的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