函数参数的传递
原创...大约 3 分钟
函数的参数传递本质上就是:从实参到形参的赋值操作。Python 中“一切皆对象”,所有的赋值操作都是“引用的赋值”。所以,Python 中参数的传递都是“引用传递”,不是“值传递”。
具体操作时分为两类:
- 对“可变对象”进行“写操作”,直接作用于原对象本身。
- 对“不可变对象”进行“写操作”,会产生一个新的“对象空间”,并用新的值填充这块空间。
相关信息
可变对象有:
- 字典、列表、集合、自定义的对象等
不可变对象有:
- 数字、字符串、元组、function 等
参数传递:传递可变对象的引用
传递参数是可变对象(例如:列表、字典、自定义的其他可变对象等),实际传递的还是对象的引用。在函数体中不创建新的对象拷贝,而是可以直接修改所传递的对象。
b = [10, 20]
def f2(m):
print("m:", id(m)) # b和m是同一个对象
m.append(30) # 由于m是可变对象,不创建对象拷贝,直接修改这个对象
f2(b)
print("b:", id(b))
print(b)
参数传递:传递不可变对象的引用
传递参数是不可变对象(例如:int、float、字符串、元组、布尔值),实际传递的还是对象的引用。在”赋值操作”时,由于不可变对象无法修改,系统会新创建一个对象。
a = 100
def f1(n):
print("n:", id(n)) # 传递进来的是a对象的地址
n = n + 200 # 由于a是不可变对象,因此创建新的对象n
print("n:", id(n)) # n已经变成了新的对象
print(n)
f1(a)
print("a:", id(a))
显然,通过 id 值我们可以看到 n 和 a 一开始是同一个对象。给 n 赋值后,n 是新的对象。
参数类型
位置参数
函数调用时,实参默认按位置顺序传递,需要个数和形参匹配。按位置传递的参数,称为:“位置参数”。
def f1(a,b,c):
print(a,b,c)
f1(2,3,4)
f1(2,3) #报错,位置参数不匹配
默认值参数
我们可以为某些参数设置默认值,这样这些参数在传递时就是可选的。称为“默认值参数”。默认值参数放到位置参数后面。
def f1(a,b,c=10,d=20): #默认值参数必须位于普通位置参数后面
print(a,b,c,d)
f1(8,9) # 8 9 10 20
f1(8,9,19) # 8 9 19 20
f1(8,9,19,29) # 8 9 19 29
命名参数
我们也可以按照形参的名称传递参数,称为“命名参数”,也称“关键字参数”。
f1(a, b, c):
print(a, b, c)
f1(8, 9, 19) # 位置参数
f1(c=10, a=20, b=30) # 命名参数
可变参数
可变参数指的是“可变数量的参数”。分两种情况:
*param
(一个星号),将多个参数收集到一个“元组”对象中。**param
(两个星号),将多个参数收集到一个“字典”对象中。
def f1(a, b, *c):
print(a, b, c) # 8 9 (19, 20)
f1(8, 9, 19, 20)
def f2(a, b, **c):
print(a, b, c) # 8 9 {'name': 'jiamei', 'age': 18}
f2(8, 9, name="jiamei", age=18)
def f3(a, b, *c, **d):
print(a, b, c, d) # 8 9 (20, 30) {'name': 'jiamei', 'age': 18}
f3(8, 9, 20, 30, name="jiamei", age=18)
强制命名参数
在带星号的“可变参数”后面增加新的参数,必须在调用的时候“强制命名参数”
def f1(*a, b, c):
print(a, b, c)
# f1(2,3,4) #会报错。由于a是可变参数,将2,3,4全部收集。造成b和c没有赋值。
f1(2, b=3, c=4) # (2,) 3 4
Powered by Waline v2.15.7