函数的参数
定义函数时()
里的参数叫做形参(形式参数),它只是一个变量名,接受调用时传递的实参,仅供函数体中的代码调用。
函数调用时,传入()
里的参数叫实参(实际参数),它是实际的数据,会传递给形参。
形参
根据形参的功能和定义方式可以分为:
- 必须参数
- 默认参数
- 动态参数
- 位置动态参数
- 关键字动态参数
必须参数
在定义函数时,如果要求调用者必须传递实参给这个形参,那么这个形参就要定义为必须形参。
直接定义在函数名后的()
里的形参就是必须形参。
例如上一节中的my_print
函数中的content
和count
。我们再来看一个案例:
定义一个函数,接收两个数,然后打印它们的和
>>> def add(x,y):
... print(x+y)
>>> add(1) # 调用时必须传递实参给必须参数,否则报错
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() missing 1 required positional argument: 'y'
>>> add(1,2)
3
默认参数
在定义函数时,某些形参有默认值,在调用时可以不接收实参,这种情况就可以定义为默认形参。
在函数名后()
中,以参数名=默认值
的形式定义的形参就是必须参数。
注意:默认参数必须定义在必须参数的后面
案例:
定义一个函数,它接收两个参数content
和count
content
是函数要打印的内容
count
是函数打印的次数,如果不传递count
默认打印1
次
>>> def my_print(content, count=1):
... for i in range(count):
... print(content)
# 调用
>>> my_print('好好学习,天天向上!')
'好好学习,天天向上!'
>>> my_print('好好学习,天天向上!', 2)
'好好学习,天天向上!'
'好好学习,天天向上!'
调用函数时传递实参给默认形参会覆盖默认值。
动态参数
在定义函数时,不确定在调用时会传递多少个实参,可以定义为动态形参。
动态形参根据实参的传递方式又分为两种。
位置动态参数
在函数名后的()
中,在形参前加*
号,这个形参就被定义为位置动态参数,通常位置动态参数的参数名为args
。
它用来接收函数调用时,以位置形式传递过来的超过形参数量的多余的实参。
注意:位置动态参数必须定义在默认参数后面。
位置动态参数会将所有多余的位置实参创建成一个元组。
>>> def func(a, *args):
... print(args, type(args))
>>> func(1,2,3,4)
(2, 3, 4) <class 'tuple'>
案例:
定义一个函数,接受2个以上的数,打印它们的和。
>>> def add(x, y, *args):
... sum = x + y
... for i in args:
... sum += i
... print(sum)
>>> add(1, 2, 3, 4)
10
关键字动态参数
在函数名后的()
中,在形参前加**
号,这个形参就被定义为关键字动态参数,通常关键字动态参数的参数名为kwargs
。
它用来接收函数调用时,以关键字形式传递过来的超过形参数量的多余的实参。
注意:关键字动态参数必须定义在位置动态参数的后面。
关键字动态参数会将多余的关键字实参创建成一个字典
>>> def func(a, **kwargs):
... print(kwargs, type(kwargs))
>>> func(a=1,b=2,c=3,d=4)
{'b': 2, 'c': 3, 'd': 4} <class 'dict'>
实参
调用函数时传递实参有两种方式:
- 位置传递
- 关键字传递
位置传递
调用函数时,在小括号中以(实参1,实参2,...)
的形式传递的实参会按照位置与形参一一对应,以这种方式传递的实参叫做位置实参。
案例:
定义一个函数实现打印一个数的n
次幂。
>>> def my_power(x, n):
... print(x**n)
>>> my_power(3,2) # 3传递给x,2传递给n
9
>>> my_power(2,3) # 2传递给x,3传递给n
8
关键字传递
调用函数时,在小括号中以(形参1=实参1,形参2=实参2,...)
的形式,显式的指定形参与实参的对应关系,以这种方式传递的实参叫做关键字实参。
注意:关键字实参必须写在位置实参的后面。
案例:
使用关键字的方式调用my_power
函数
>>> my_power(x=3,n=2)
9
>>> my_power(n=2,x=3)
9
>>> my_power(3,n=2)
9
参数解包
当一个函数接收多个参数时,如果参数存储在一个列表或一个字典中时,调用起来非常不方便。看下面的案例:
>>> def func(a, *args):
... print(args, type(args))
>>> ls = [1,2,3,4,5,6]
>>> fun(ls[0],ls[1],ls[2],ls[3],ls[4],ls[5])
1 2 (3, 4, 5, 6)
>>> def func(a, **kwargs):
... print(kwargs, type(kwargs))
>>> dc = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
>>> fun(a=dc['a'], b=dc['b'], c=dc['c'], d=dc['d'])
1 2 {'c': 3, 'd': 4}
可以看到上面的案例调用时的不便,参数解包就是为了解决这些问题的。
*
解包
在传递实参时,可以通过*
对可迭代对象进行解包。
>>> func(ls[0],ls[1],ls[2],ls[3],ls[4],ls[5])
1 2 (3, 4, 5, 6)
>>> func(*ls) # 与上面的写法等价
1 2 (3, 4, 5, 6)
**
解包
在传递实参时,可以通过**
对字典进行解包。
>>> fun(a=dc['a'], b=dc['b'], c=dc['c'], d=dc['d'])
1 2 {'c': 3, 'd': 4}
>>> fun(**dc) # 与上面的写法等价
1 2 {'c': 3, 'd': 4}