Python中函数的各种类型参数解读
作者:猎风工作室
Python中函数的参数类型非常丰富多彩。
Python的函数支持的参数类型包括:
- (1)位置参数
- (2)默认参数
- (3) 可变参数
- (4)关键字参数
- (5)命名关键字参数
接下来,我们一一来学习一下:
1.位置参数
位置参数,就是普通的参数。写在函数名后的小括号中,
如下面例子:
def power(x): return x * x def power(x, n): s = 1 while n > 0: n = n - 1 s = s * x return s
2.默认参数
默认参数允许函数设置参数的默认值。例如:
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
如果可以设计一个不变对象,那就尽量设计成不变对象。
3.可变参数
参数个数不确定,可以用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
4.关键字参数
关键字参数扩展函数的功能。 允许你传入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
5.命名关键字参数
命名关键字参数:限制关键字参数的名字。例如:只接收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
6.参数的组合
在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。
参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
7.练习
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': '#'}
8.参数组合
对于任意函数,都可以通过类似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
9.参数解包(拆包)
传递实参时,可以在序列类型的参数前添加星号,这样他会自动将序列中的元素依次作为参数传递。
例如:
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
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。