Python中函数的参数类型非常丰富多彩。
Python的函数支持的参数类型包括:
(1)位置参数
(2)默认参数
(3) 可变参数
(4)关键字参数
(5)命名关键字参数
接下来,我们一一来学习一下:
位置参数,就是普通的参数。写在函数名后的小括号中,如下面例子:
def power(x):
return x * x
def power(x, n):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
默认参数允许函数设置参数的默认值。例如:
def power(x, n = 2):......
其中参数n的默认值为2,调用函数时,可以省略这个参数,如:power(5),这里的5会赋值给x。
注意事项:
1.必选参数在前,默认参数在后。
Why?因为Python中函数的实际参数与形式参数的匹配顺序是从左至右的。
2.如何设置默认参数?
变化大的参数放前面,变化小的参数放后面当默认的参数。
降低函数调用的难度。
例如:在某校的学生信息管理系统中,可以把年龄和城市设为默认参数(因为都在一个城市,同年级的年龄也大都相同)。
def enroll(name, gender, age=6, city='Beijing'):
print('name:', name)
print('gender:', gender)
print('age:', age)
print('city:', city)
3.可以不按顺序提供部分默认参数。当不按顺序提供部分默认参数时,需要把参数名写上。
如:
enroll('Bob', 'M', 7)
enroll('Adam', 'M', city='Tianjin')
4.一个默认参数的大坑。
先定义一个函数,传入一个list,添加一个END再返回.
def add_end(L=[]):
L.append('END')
return L
试着用默认参数,连续执行add_end?
你会发现,似乎函数每次都“记住了”上次添加了’END’后的list。
原因是:
Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。
默认参数强烈建议指向不变对象!可以用None这个不变对象来实现。
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L
如果可以设计一个不变对象,那就尽量设计成不变对象。
参数个数不确定,可以用list和tuple来充当参数,但是需要现行构造。
形式:
在参数名字前加 “*”号。
调用时可传入任意个(包括0个)参数。
可变参数在调用时自动组装为一个tuple。
list参数和tuple参数前加“*”可作为可变参数使用。
接下来,我们用例子来学习一下可变参数的用法。
需求:计算
利用list或tuple为参数,可实现如下代码:
def calc(numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
>>> calc([1, 2, 3])
14
>>> calc((1, 3, 5, 7))
84
但是用户在调用函数时,需要事先构造好一个list或tuple的数据集。
如果是用可变参数,用户可以直接输入数据集,用逗号隔开,并且数据个数无硬性限制。
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
>>> calc(1, 2)
5
>>> calc()
0
在调用具有可变参数的函数时,可以利用list或tuple前加星号的形式来充当可变参数实参。
如:
>>> nums = [1, 2, 3]
>>> calc(*nums)
14
关键字参数扩展函数的功能。 允许你传入0个或任意个含参数名的参数,在函数内部自动组装为一个dict。
如:
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'}
一个dict参数可以当成一个关键字参数
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
注意:person函数内部对extra的改变是改变的extra的副本,对extra这个dict本身并没有做出改变。
试想你正在做一个用户注册的功能,除了用户名和年龄是必填项外,其他都是可选项,利用关键字参数来定义这个函数就能满足注册的需求。
可变参数和关键字参数使用时机和形式
可变参数:
定义函数时,形式参数+‘*’,表示可变参数,使用时,直接输入可变数量的参数
使用函数时,实际参数+‘*’,实际参数本身必须是一个list或者touple。
关键字参数:
定义函数时,形式参数+‘**’,表示关键字参数,使用时,直接以“键=‘值’”的形式输入
使用函数时,实际参数+‘**’,实际参数本身必须是一个dict
命名关键字参数:限制关键字参数的名字。例如:只接收city和job作为关键字参数。
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)
命名关键字参数必须传入参数名,否则报错
命名关键字参数可以有缺省值
def person(name, age, *, city='Beijing', job):
print(name, age, city, job)
>>> person('Jack', 24, job='Engineer')
Jack 24 Beijing Engineer
在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。
参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
def f1(a,b,c=0,*args,**kw):
print('a =',a,'b =',b,'c =',c,'args = ',args,'kw = ',kw)
def f2(a,b,c=0,*,d,**kw):
print('a =',a,'b =',b,'c =',c,'d = ',d,'kw = ',kw)
f1(1,2)
f1(1,2,3)
f1(1,2,3,'a','b')
f1(1,2,3,'a','b',x = 99)
f2(1,2,3,d = 'aaa',ext = None)
args = (1,2,3,4)
kw = {'d':99,'x':'#'}
f1(*args,**kw)
args = (1,2,3)
kw = {'d':99,'x':'#'}
f2(*args,**kw)
答案:
a = 1 b = 2 c = 0 args = () kw = {}
a = 1 b = 2 c = 3 args = () kw = {}
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
a = 1 b = 2 c = 3 d = aaa kw = {'ext': None}
a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}
a = 1 b = 2 c = 3 d = 99 kw = {'x': '#'}
对于任意函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参数是如何定义的。
不要同时使用太多的组合,否则函数接口的可理解性很差。
例如:
#以下函数允许计算两个数的乘积,请稍加改造,变成可接收一个或多个数并计算乘积
def product(x, y):
return x * y
测试程序如下:
print('product(5) =', product(5))
print('product(5, 6) =', product(5, 6))
print('product(5, 6, 7) =', product(5, 6, 7))
print('product(5, 6, 7, 9) =', product(5, 6, 7, 9))
if product(5) != 5:
print('测试失败!')
elif product(5, 6) != 30:
print('测试失败!')
elif product(5, 6, 7) != 210:
print('测试失败!')
elif product(5, 6, 7, 9) != 1890:
print('测试失败!')
else:
try:
product()
print('测试失败!')
except TypeError:
print('测试成功!’)
答案:
def product(x, *num):
for n in num:
x = x * n
return x
传递实参时,可以在序列类型的参数前添加星号,这样他会自动将序列中的元素依次作为参数传递。
例如:
def fn1(a,b,c):
print(a, b, c)
x = (1,2,3) # 元组数据
y = [4,5,6] # 列表数据
z = {'a':7, 'b':8, 'c':9} # 字典数据
fn1(*x) # 元组解包 *
fn1(*y) # 列表解包 *
fn1(**z) # 字典解包 通过 **对字典进行解包
# 输出为
1 2 3
4 5 6
7 8 9
学会了就点个赞吧。