python函数参数类型之位置参数、默认参数、动态参数、关键字参数

1. 位置参数

位置参数是指按照函数定义时的参数顺序来传递实参。举个例子:

def greet(name, message):

print(f"{name}, {message}")

greet("Lucy", "Good morning!")

在这个例子中,namemessage是位置参数,当我们调用greet("Lucy", "Good morning!")时,"Lucy"就被赋值给了name"Good morning!"被赋值给了message

调用函数时,我们可以根据参数位置来传递实参,例如:greet("John", "How are you?")。如果我们传递的参数位置与函数定义时的顺序不一致,那么会出现错误。

一旦定义了一个位置参数,调用函数时必须传递对应数量的参数值。如果传递的参数数量不对,Python解释器会抛出一个TypeError。

1.1 *args语法:传递任意数量的位置参数

如果我们想传递任意数量的位置参数,可以使用*args语法,如下所示:

def greet(*names):

for name in names:

print(f"Hello, {name}")

greet("Lucy", "John", "Mike")

在这个例子中,*names定义了一个元组,接收所有给定的位置参数,Python解释器把这些参数打包成一个元组传递给函数。可以看到,在调用greet函数时传递三个参数,因为*names表示可以接收任意数量的位置参数,所以它们都被打包为一个元组,程序输出如下:

Hello, Lucy

Hello, John

Hello, Mike

值得一提的是,通过*args方式传递位置参数实现的灵活性相当强悍,但对于代码可读性造成一定的影响,因此,使用*args时建议在函数名和元组形参名之间加上注释对代码进行说明。

2. 默认参数

如果我们写了一个函数,希望部分参数有默认值,一旦函数有了这些默认值,函数调用的代码就会变得简洁明了。这时我们可以使用默认参数。

一个默认参数允许指定一个缺省值,如果未传递这个参数的值,则会使用该缺省值。

下面给一个例子:

def greet(name, message="Good morning!"):

print(f"{name}, {message}")

greet("Lucy")

在这个例子中,我们给message参数设置了一个默认值"Good morning!",因此当我们调用greet("Lucy")时,"Good morning!"这个默认值就会被使用。

需要注意的是,如果一个默认参数值被设为一个可变对象(比如Python中的列表或字典),则这个默认参数值在所有函数调用之间共享,这可能会产生意想不到的副作用。

3. 动态参数

当不确定参数个数时,我们可以使用动态参数。

3.1 *args语法:传递任意数量的位置参数

我们已经在位置参数中使用过*args了,现在我们可以使用*args参数语法来实现动态参数。下面的例子展示了如何使用*args来接收任意数量的位置参数:

def greet(*names, message):

for name in names:

print(f"{name}, {message}")

greet("Lucy", "John", "Mike", message="Good morning!")

需要注意的是,从语法上来讲,*args语法可以和位置参数一起使用也可以不一起使用,它只是表示可以接收任意数量的位置参数而已。

3.2 **kwargs语法:传递任意数量的关键字参数

动态参数也可以接收任意数量的关键字参数,例如下面的例子:

def greet(**names):

for key, value in names.items():

print(f"{key} is {value}")

greet(Lucy="Female", John="Male", Mike="Male")

在这个例子中,我们使用**names语法定义了一个dict,函数可以接收任意数量的关键字参数,每一个参数将被绑定到names字典中。

需要注意的是,从语法上来讲,**kwargs语法可以和关键字参数一起使用也可以不一起使用,它只是表示可以接收任意数量的关键字参数而已。

4. 关键字参数

我们还可以在函数调用参数列表中使用关键字参数,这时候函数会知道关键字所对应的是哪个参数。

4.1 带有默认值的关键字参数

我们可以使用默认参数语法来带有默认值的关键字参数。

def greet(name, message="Good morning!"):

print(f"{name}, {message}")

greet(name="Lucy")

在这个例子中,我们给message参数设置了一个默认值"Good morning!",然后使用greet(name="Lucy")来调用函数。因为我们已经指定了name参数,所以Python解释器知道我们应该把message参数绑定到默认值"Good morning!"上。

4.2 带有不带默认值的关键字参数

如果我们在函数定义时不想给某个参数设置默认值,但又希望在函数调用时可以使用关键字参数来传递参数,则可以按照如下示例:

def greet(name1, name2, message):

print(f"{name1}, {name2}, {message}")

greet(name1="Lucy", name2="John", message="Good morning!")

在这个例子中,我们通过name1="Lucy"语法为name1参数传递了一个值,然后通过name2="John"语法为name2传递了一个值。

值得一提的是,关键字参数在函数调用时可以与位置参数混合使用,但是需要注意一个规则:关键字参数必须放在位置参数的后面。

5. 放在一起看

我们来举个结合前面知识点方便理解的例子。

def greet(*names, message="Good morning!", **emails):

for name in names:

print(f"{name}, {message}")

for key, value in emails.items():

print(f"{key} is {value}")

greet("Lucy", "John", "Mike", message="Good morning!", Lucy="Lucy@example.com", John="John@example.com")

在这个例子中,我们使用了位置参数、默认参数和关键字参数。

我们使用*names语法来实现动态参数,以便我们可以传递任意数量的位置参数。然后使用之前介绍的默认参数语法将message设置为缺省字符串"Good morning!"。最后,我们使用**emails语法带有任意数量的键值对关键字参数来传递个性化的邮件地址。

从输出结果可以看出程序执行了两步操作。在第一步中,循环遍历所有名字,输出格式化后的问候语。在第二步中,循环遍历所有关键字参数并输出格式化后的结果。

总结

本文主要介绍了四种Python函数参数类型:位置参数、默认参数、动态参数和关键字参数,并且提供了针对每类参数的相应语法和实际应用中的案例样例。Python给函数参数的使用带来了灵活性,以便开发者可以根据自己的需求来定义适当的函数参数,达到半自动化的效果。

后端开发标签