一般最开始接触也就是最简单的函数参数形如 def fuc(x) ,但是也有复杂的函数参数传递方式,总结一下python的传参方式,先介绍一下参数的基本类型,最后讲到最复杂的(**params)类型。
1. 位置参数
一个最简单的函数形式,其中x,y就是位置参数:
def add_both(x, y):
return x+y
2. 默认参数
- 最大的好处是能降低调用函数的难度;
- 必选参数在前,默认参数在后,否则Python的解释器会报错;
- 当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。
def enroll(name, gender, age=6, city='Beijing'):
print('name:', name)
print('gender:', gender)
print('age:', age)
print('city:', city)
有多个默认参数时,调用的时候,既可以按顺序提供默认参数,比如调用enroll('Bob', 'M', 7)
,意思是,除了name
,gender
这两个参数外,最后1个参数应用在参数age
上,city
参数由于没有提供,仍然使用默认值。
也可以不按顺序提供部分默认参数。当不按顺序提供部分默认参数时,需要把参数名写上。比如调用enroll('Adam', 'M', city='Tianjin')
,意思是,city
参数用传进去的值,其他默认参数继续使用默认值。
默认参数的坑:
def add_end(L=[]): L.append('END') return L
连续调用默认参数调用add_end(),默认参数是
[]
,但是函数似乎每次都“记住了”上次添加了'END'
后的list,原因解释如下:
Python函数在定义的时候,默认参数
L
的值就被计算出来了,即[]
,因为默认参数L
也是一个变量,它指向对象[]
,每次调用该函数,如果改变了L
的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]
了。>>> add_end() ['END'] >>> add_end() ['END', 'END']
定义默认参数要牢记一点:默认参数必须指向不变对象,这也是为什么大多数函数默认参数都是None;
def add_end(L=None): if L is None: L = [] L.append('END') return L
为什么要设计
str
、None
这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。
3. 可变参数
可变参数就是传入的参数个数是可变的,可以是任意个。
类似最常见的情况就是传入的参数是list或者tuple,运用在循环里:
def cal_num(nums):
for i in nums:
print(i)
>>> cal_num([1, 2])
1
2
而定义可变参数就是在参数前加一个*号,改为可变参数;参数nums
接收到的是一个tuple,函数代码完全不变。调用函数的时候传入任意个参数,包括0个;
def cal_num(*nums):
for i in nums:
print(i)
>>> cal_num(1, 2)
1
2
如果已经有一个list或者tuple,要调用一个可变参数怎么办?Python允许你在list或tuple前面加一个*
号,把list或tuple的元素变成可变参数传进去; *nums
表示把nums
这个list的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。
>>> nums = [1, 2]
>>> cal_num(*nums)
1
2
4. 关键字参数
可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。
函数person
除了必选参数name
和age
外,还接受关键字参数kw
。在调用该函数时,可以只传入必选参数,也可以传入任意个数的关键字参数:
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
>>> person('Michael', 30)
name: Michael age: 30 other: {}
>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
4. 命名关键字参数
如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city
和job
作为关键字参数。和关键字参数**kw
不同,命名关键字参数需要一个特殊分隔符*
,*
后面的参数被视为命名关键字参数。
def person(name, age, *, city, job):
print(name, age, city, job)
>>> person('Jack', 24, city='Beijing', job='Engineer')
Jack 24 Beijing Engineer
如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*
了。命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错。
def person(name, age, *args, city, job):
print(name, age, args, city, job)
参考链接:https://www.liaoxuefeng.com/wiki/1016959663602400/1017261630425888