函数参数
-
函数的定义与使用
def 函数名([参数列表]): '''注释''' 函数体
- 函数形参不需要声明起类型,也不需要制定函数的返回值类型。
- 及时改函数不需要接受任何参数,也必须保留一对空的括号。
- 括号后面的冒号必不可少。
- 函数体相对于def关键字必须保持一定的空格缩进。
- Python允许嵌套定义函数
-
函数参数
在Python中,函数参数有很多种:可以为普通参数、默认值参数、关键参数、可变长度参数等等。
Python在定义函数时不需要指定形参的类型,完全由调用者传递的实参类型以及Python解释器的理解和推断来决定,类似于重载和泛型。
-
位置参数
调用函数时实参和形参的顺序严格一致,比起实参和形参的数量必须相同
def demo(a,b,c): #所有形参都是位置参数 print(a,b,c) >>>demo(2,3,4) 2,3,4 >>>demo(2,3,4,5) #实参与形参的数量必须相同 demo() takes 3 positional arguments but 4 were given
-
默认值参数
调用带有默认值参数的函数时,可以不对默认值参数进行赋值,也可以为其赋值,具有很大的灵活性。
def say(message,times = 1,sx = 2): 函数体 >>> say(1,2) 1 2 2 >>> say.__defaults__ (1, 2)
函数名.__ defaults__ 可以查看函数所有默认值参数的当前值,返回胃一个元组,元素依次表示每个默认值的当前值。
注意:默认值参数必须出现在函数参数列表的最右端,任何一个默认值参数右边不能有非默认值参数。
-
关键参数
关键字参数主要只调用函数时的参数传递方式,通过关键参数,实参顺序可以和形参顺序不一致,但不影响传递结果,避免了用户需要牢记位置参数顺序的麻烦。
>>> say(2,sx=3) 2 1 3
-
可变长度参数
-
可变长度参数主要有两种形式:在参数名前加1个*或2个**
-
*parameter用来接受多个实参并将其放在一个元组中
-
**parameter接受多个关键参数并存放到字典中
*parameter的用法
无论调用该函数时传递了多少实参,一律将其放入元组中
>>> def demo(*p): print(p) >>> demo(1,2,3) (1, 2, 3) >>> demo(1,2) (1, 2) >>> demo(1,2,3,4,5,6,7) (1, 2, 3, 4, 5, 6, 7)
**parameter的用法
调用该函数时自动将接受的参数转换为字典
>>> def demo(**p): for item in p.items(): print(item) >>> demo(x=1,y=2,z=3) ('y', 2) ('x', 1) ('z', 3)
在函数定义中增加一些外围的检查代码,可以防止用户调用函数时传入无效参数。
def demo(a,b,**kwargs): for para in kwargs.keys(): if para not in ('x','y','z') raise Exception('{0}is not a valid parameter'.format(para)) print(a+b+sum(kwargs.values())) # 只能接收'x','y','z',这三个参数
定义函数时可以同时使用位置参数,关键参数,默认参数和可变长度参数。一般不要这样做
降低可读性,查错困难,函数设计不好,不满足模块高内聚的要求。
-
-
强制函数的某些参数必须以关键参数形式进行传值
在函数定义是,位于*parameter活单独一个星号 *之后的所有参数都只能以关键参数的形式进行传值,不接收其他任何形式的传值。
如果需要强制所有参数都必须以关键参数形式进行传值,可以在定义函数时把单独以个星号*作为函数第一个参数。
>>> def demo(a, b, *, c): ... print(a+b+c) ... >>> demo(1,2,c=2) 5 >>> def demo(a, b, *p, c): ... print(a+b+c+sum(p)) ... >>> demo(1,2,3,4,5,c=6) 21
-
传递参数是的序列解包
序列解包是非常重要且常用的一个功能。
>>> lt = [1,2,3] >>> a, b, c = lt >>> print(a,b,c) 1 2 3 >>> x, y, z = 1, 2, 3 >>> print(x,y,z) 1 2 3 >>> a_tuple=tuple(range(3)) >>> x,y,z = a_tuple >>> print(x,y,z) 0 1 2 >>> x, y, z = map(str, range(3))
在Python列表、元组、集合、字典以及其他可迭代对象,对字典使用时,默认是对字典“键”进行操作,Python解释器将自动进行解包。对“键:值” 对进行操作使用字典的
items()
方法,对“值”进行操作应使用values()
方法进行指定。>>> s = {'a':1,'b':2} >>> a,b = s >>> a 'a' >>> a,b = s.items() >>> b ('b', 2) >>> a,b = s.values() >>> a 1 >>> a,b,c='ABC' >>> a 'A'
特殊用法:
>>> print(*[1,2,3],4,*(5,6)) 1 2 3 4 5 6 >>> *range(3),3 (0, 1, 2, 3) >>> {*range(3),3,4} {0, 1, 2, 3, 4} >>> {'a':1,**{'b':2}} {'a': 1, 'b': 2}
序列解包逆运算
>>> a, *b, c = 1,2,3,4,5 >>> a,b,c (1, [2, 3, 4], 5) >>> a,*b,c=tuple(range(20)) >>> b [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
传递参数是的序列解包
>>> def demo(a,b,c): ... print(a,b,c) ... >>> seq = [1,2,3] >>> demo(*seq) 1 2 3 >>> seq = {1:'a',2:'b',3:'c'} >>> demo(*seq) 1 2 3 >>> demo(*seq.values()) a b c
如果实参是字典 可以使用两个星号
**
进行解包,会把字典转换成类似于关键字参数的形式进行参数传递。要求实参字典中的所有键都必须是函数的形参名称,或者于函数中两个星号的可变长度参数相对应。>>> p = {'a':1,'b':2,'c':3} >>> def f(a,b,c=5): ... print(a,b,c) ... >>> f(**p) 1 2 3 >>> def demo(**p): ... for item in p.items(): ... print(item) ... >>> demo(**p) ('a', 1) ('b', 2) ('c', 3)
一个函数需要以多种新式来接收参数,定义时一般把位置参数放在最前面,然后是默认值参数,接下来是一个星号的可变长度参数,最后两个星号的可变长度参数;调用函数是,一般也按照这个顺序进行参数传递。调用函数时如果对实参使用一个星号* 进行序列解包,那么这些解包后的实参将会被当做普通位置参数对待,并且会在关键参数和使用两个星号** 进行解包的参数之前进行处理。
-