函数就像是一个黑盒子,我们将相关的一些功能打包成一个函数,后续再调用的时候,我们不再关心内部如何实现,而是只关心这个函数需要输入(Input)什么,需要输出(Output)什么。 其中函数的输入就是参数,输出就是Return。
Python支持的参数有四种类型:
必选参数
默认参数
可变参数
关键字参数
下面我们来一一介绍一下。
必选参数
必选参数就是调用一个函数时,必须输入的参数。
例如我们定义一个函数
def my_sum(x,y):
return x+y
此时,my_sum函数的x,y参数就是必选参数,在调用该函数时候必须输入,不可以省略。
默认参数
默认参数是指在调用函数时可选择性的输入或者不输入。不输入时,则参数为默认值。例如我们定义一个用于打印学生信息的函数。学生的信息包括姓名、年龄、生源。这些学生大多数来自浙江省,那么这个函数可以这么定义:
def print_info(name,age=20,province="Zhejiang"):
print name,age,province
对于大多数浙江的学生且年龄都是20,我们只需要这么调用函数即可:print_info('Lilei')。此时我们并没有输入province参数,函数默认为年龄20,生源为Zhejiang。
对于少数来自外省的学生,且年龄不为20的学生,我们可以这么按顺序排列默认参数,即先年龄,后生源,顺序与函数定义的时候一致:
print_info('Lucy',21,'Jiangsu')。此时province就修改成Jiangsu了。
如果需要跳过某个默认参数或则不按顺序传入默认参数,我们则需要写上参数名。例如:print_info('Tom',province='Hebei')。
使用默认参数可以大大降低函数调用的复杂性。例如对于有很多参数的函数,某些参数在实际业务中经常变化,有些参数缺较少变化。我们可以将这些参数按其在实际业务中的变化频率从高到底排列,并对变化频率低的参数设为默认参数。实际调用时,我们只需要传入必要的参数值即可。这样我们可以实现只定义一个函数却能满足多种情境。
默认参数的坑
默认参数的默认值指向的必需时不变对象。
举一个例说明当函数的默认参数默认为一个可变对象时,会出现什么状况。
def add_item(items=[]):
items.append('apple')
return items
我们想要实现的功能是,调用该函数,会对传入的list最后添加一个apple元素。若 `items`参数未传入,则默认是一个空list。
当我们第一次调用add_item()函数时,返回['apple'],没什么错误。
但我们再一次调用add_item()函数时,却返回了`['apple','apple']。这与我们预期的不相符合。因为我们第二次调用也未传入任何参数。
其原因是add_item()函数的默认参数在函数定义的时候就已经在内存生成。第一次、第二次的默认参数指向的是同一个list对象。其一次调用函数对该list对象的修改会影响后一次函数的调用。
可变参数
在实际情况下,我们经常会碰到某函数的参数个数不一定的情况。例如我们想要写一个计算几个数字的平方和的函数。
当然我们可以预先将这些数字组装成一个list或者tuple再传入函数。代码如下:
# 定义函数
def quadratic_sum(numbers):
sum = 0
for number in numbers:
sum = sum + number
return sum
# 先将数字组成一个list
ns = [1,3,2,6,2]
# 将list传入函数
quadratic_sum(ns)
在Python中,我们可以直接定义一个有可变参数的函数,我们无需预先组装一个list或者tuple,而直接传入函数。可变参数的表示方法是在参数名前加一个*。
传入的可变参数会被Python组装成一个tuple,tuple名即为函数定义的可变参数名。
# 定义一个有可变参数的函数
def quadratic_sum(*numbers):
sum = 0
for number in numbers:
sum = sum + number
return sum
# 直接调用函数,无需预先组装成一个list或者tuple。
quadratic_sum(1,3,2,6,2)
此时我们已经有了一个支持可变参数的函数,但是我们现在又有一个list比如[1,3,2,6,2]。我们还需要把这个list一个拆成一个数字传入函数吗?显然这么做不科学。
Python提供了一个简单的解决方案。我们只需要在传入的list名前加一个*,Python就会帮我们把这个list或tuple拆成可变参数传入。例如:
ns = [1,2,3,54,2]
quadratic_sum(*ns)
关键字参数
关键字参数于可变参数类似。关键字参数可以将传入的参数组装成一个字典Dict。
定义一个关键字参数的方法就是在关键字参数前写**。例如
def user_info(name,age,**kw):
print 'Name:',name,'Age:',age,'Keyword:',kw
# 调用函数
user_info('Charlie',20,gender='male',city='Hangzhou')
输出结果:
Name: Chalrie Age: 20 Keyword: {'gender': 'male', 'city': 'Hanzhou'}
当然,如果已经又一个dict对象,也可以在传入时的dict名前输入**,Python会自动将Dict拆分成关键字参数。
keyword = {'gender': 'male', 'city': 'Hanzhou'}
user_info("charlie",20,**keyword)
参数组合
Python函数的参数可以是上述四种参数的任意组合,但是其顺序必须是必选参数、默认参数、可变参数、关键字参数。Python会根据这个顺序进行匹配。例如我们定义一个函数:
def func(name,age=20,gender='female',*args,**kw):
print "age:",age
print "name:",name
print args
print kw
上面这个函数,name是必选参数。调用该函数时若没有传入name参数,则会报错。
age,gender是默认函数。可以传入也可以不传入。不传入则是默认值。
其余无关键字的参数会被组装成一个叫argstuple。
其余有关键字的参数会被组装成一个叫kw的dict。
例如:
func('Charlie',gender="male",2,3,4,city="hangzhou",province="Zhejiang")