函数参数

位置参数

参数的位置至关重要, 函数调用时, 根据位置顺序将实参传递给形参, 传入的实参的数量和位置都必须和定义函数时保持一致.

实参和形参数量必须一致

在调用函数时, 传入的实参的数量, 必须和形参数量一致(传多传少都不行), 否则Python解释器会抛出TypeError异常.

Example:

# 函数定义了2个形参
def girth(width, height):
    return 2 * (width + height)

# 函数调用时必须传递2个实参
# 否则会引发异常
print(girth(2))
print(girth(2, 3, 4))

实参和形参位置必须一致

在调用函数时, 传入的实参的位置必须和形参位置一致, 否则会产生以下两种结果:

  • 引发TypeError异常

当实参类型和形参类型不一致时, 并且这两种类型之间不能正常转换, 此时就会引发TypeError异常.

  • 产生的结果和预期不符

调用函数时, 如果指定的实参和形参的位置不一致, 但它们的数据类型相同, 那么程序不会引发异常, 只不过导致运行结果和预期不符.

关键字参数

关键字参数, 是指根据形参的名字来确定输入的参数值. 通过此种方式指定函数实参, 不再需要与形参的位置完全一致, 只要将参数名字写正确即可.

在调用函数时, 可以使用位置参数, 也可以使用关键字参数, 还可以混合使用位置参数和关键字参数.

Example:

def f(str1, str2):
    print(str1, str2)

f('hello', 'world')
f(str1='hello', str2='world')
f('hello', str2='world')

但是需要注意, 混合使用位置参数和关键字参数, 关键字参数必须位于所有的位置参数之后.

注解

尽量不要混合使用位置参数和关键字参数, 因为这容易引起混乱.

默认参数

在调用函数时如果不指定某个参数, Python解释器会抛出异常. 为了解决这个问题, Python允许为参数设置默认值, 即在定义函数时, 直接给形参指定一个默认值. 这样的话, 如果调用函数时没有给拥有默认值的形参传递参数, 该形参就使用默认值.

Python定义带有默认值参数的函数, 其语法格式如下:

def 函数名(..., 形参名, 形参名=默认值):
    代码块

但是需要注意, 有默认值的形参必须在所有没有默认值的形参的后面, 否则会产生语法错误.

在Python中, 可以使用函数名.__defaults__查看函数的默认值参数的当前默认值, 其返回的是一个元组.

收集参数

Python在定义函数时可以使用可变参数(不定长参数), 即允许定义参数个数可变的函数. 这样在调用函数时, 可以向其传入任意多个参数.

  • 函数定义时, 形参列表中以*开头的参数, 表示一个空元组, 用来收集多余的位置参数;
*args

需要注意的是, *args会根据其在函数形参中定义的位置, 收集实参中从相应位置开始的所有位置参数. 所以, 通常将 *args作为最后一个形参, 这样, 在给前面的形参赋值之后, *args用来收集多余的值.

如果想让参数避免被*args收集, 可以使用关键字参数.

  • 函数定义时, 形参列表中以**开头的参数, 表示一个空字典, 用来收集多余的关键字参数.
**kwargs

**kwargs在形参列表中的定义位置并不影响它的功能, 但是通常将其定义在形参列表的末尾.

如果一个函数中同时定义了*args**kwargs, 通常将它们定义在形参列表的末尾:

def func(..., *args, **kwargs):
    ....

分配参数

收集参数, 是函数定义时在形参列表中定义, 在函数体中实现, 将多余的参数收集在元组或字典中.

与之相反, 分配参数, 是在函数调用时, 直接将列表, 元组, 字符串, 字典作为函数参数, 将其进行拆分, 把其中的元素分配给函数中的形参.

  • 当传入一个列表, 元组或字符串时, 其名称前要带*, 表示将其解包(依次取出各个元素), 作为位置参数传递给函数;
  • 当传入一个字典, 其名称前要带**, 表示将字典解包, 作为关键字参数传递给函数.