如何在 Python 3 中使用 *args 和 **kwargs

介绍

在函数定义中,参数是指定给定函数可以接受的参数的命名实体。

在编程时,您可能不知道代码的所有可能用例,并且可能希望为将来使用该模块的程序员或与代码交互的用户提供更多选项。我们可以通过在代码中使用*args**kwargs向函数传递可变数量的参数。

先决条件

您应该在计算机或服务器上安装了Python 3并设置了编程环境。如果尚未设置编程环境,您可以参考适用于您的操作系统(Ubuntu、CentOS、Debian等)的本地编程环境或服务器编程环境的安装和设置指南。

理解 *args

在Python中,单星号形式的*args可以用作参数,以将非关键字的可变长度参数列表发送到函数。值得注意的是,星号(*)是这里的关键元素,因为args这个词是约定俗成的惯用语,但并没有被语言强制执行。

信息:要跟随本教程中的示例代码,请在本地系统上运行python3命令以打开Python交互式Shell。然后可以在>>>提示符后复制、粘贴或编辑这些示例。

让我们看看一个使用两个参数的典型函数:

lets_multiply.py

def multiply(x, y):
    print (x * y)

在上面的代码中,我们用xy作为参数构建了函数,然后当我们调用函数时,需要使用数字与xy对应。在这种情况下,我们将整数5传递给x,将整数4传递给y

lets_multiply.py

def multiply(x, y):
    print (x * y)

multiply(5, 4)

现在,我们可以运行上面的代码:

python lets_multiply.py

我们将收到以下输出,显示整数5和4已按multiply(x,y)函数进行了相乘:

20

如果后来我们决定希望将三个数字相乘而不是仅仅两个呢?如果我们尝试向函数添加一个额外的数字,如下所示,我们将收到一个错误。

lets_multiply.py

def multiply(x, y):
    print (x * y)

multiply(5, 4, 3)
TypeError: multiply() takes 2 positional arguments but 3 were given

因此,如果您怀疑以后可能需要使用更多的参数,可以使用*args作为参数。

我们可以通过移除xy作为函数参数,并用*args替代它们,基本上创建与第一个示例相同的函数和代码:

lets_multiply.py

def multiply(*args):
    z = 1
    for num in args:
        z *= num
    print(z)

multiply(4, 5)
multiply(10, 9)
multiply(2, 3, 4)
multiply(3, 5, 10, 6)

当我们运行此代码时,我们将收到这些函数调用的乘积结果:

20
90
24
900

因为我们使用*args将可变长度参数列表发送到我们的函数,我们能够在函数调用中传递任意数量的参数。

使用*args您可以创建更灵活的代码,接受函数内不同数量的非关键字参数。

理解 **kwargs

双星号形式的**kwargs用于将一个关键字的可变长度参数字典传递给函数。同样,两个星号(**)是这里的关键元素,因为kwargs这个词是约定俗成的惯用语,但并没有被语言强制执行。

*args类似,**kwargs可以接收您想提供的任意数量的参数。然而,**kwargs*args的不同之处在于您需要为其分配关键字。

首先,让我们打印出传递给函数的**kwargs参数。我们将创建一个简短的函数来执行此操作:

print_kwargs.py

def print_kwargs(**kwargs):
        print(kwargs)

接下来,我们将调用函数,并传递一些关键字参数:

print_kwargs.py

def print_kwargs(**kwargs):
        print(kwargs)

print_kwargs(kwargs_1="Shark", kwargs_2=4.5, kwargs_3=True)

让我们运行上述程序并查看输出:

python print_kwargs.py

{'kwargs_3': True, 'kwargs_2': 4.5, 'kwargs_1': 'Shark'}

根据您当前使用的Python 3版本,字典数据类型可能是无序的。在Python 3.6及以上版本中,您将按顺序接收到键值对,但在更早的版本中,键值对将以随机顺序输出。

重要的是要注意一个名为kwargs的字典被创建,我们可以像处理其他字典一样处理它。

让我们创建另一个简短的程序,显示如何利用**kwargs。在这里,我们将创建一个函数来问候一组名字字典。首先,我们将从包含两个名字的字典开始:

print_values.py

def print_values(**kwargs):
    for key, value in kwargs.items():
        print("The value of {} is {}".format(key, value))

print_values(my_name="Sammy", your_name="Casey")

我们现在可以运行程序并查看输出:

python print_values.py

he value of your_name is Casey
The value of my_name is Sammy

同样,因为字典可能是无序的,您的输出可能是Casey的名字先出来,也可能是Sammy的名字先出来。

现在让我们向函数传递额外的参数,以显示**kwargs将接受您想包含的任意数量的参数:

print_values.py

def print_values(**kwargs):
    for key, value in kwargs.items():
        print("The value of {} is {}".format(key, value))

print_values(
            name_1="Alex",
            name_2="Gray",
            name_3="Harper",
            name_4="Phoenix",
            name_5="Remy",
            name_6="Val"
        )

当我们此时运行程序时,我们将收到以下输出,可能仍然是无序的:

The value of name_2 is Gray
The value of name_6 is Val
The value of name_4 is Phoenix
The value of name_5 is Remy
The value of name_3 is Harper
The value of name_1 is Alex

使用**kwargs为我们的程序提供了使用关键字参数的灵活性。当我们将**kwargs用作参数时,我们不需要知道最终希望传递给函数的参数数量。

参数顺序

在函数或函数调用中排列参数时,参数需要按特定顺序出现:

  1. 正式位置参数
  2. *args
  3. 关键字参数
  4. **kwargs

在实际情况中,使用显式位置参数与*args**kwargs一起工作时,您的函数看起来像这样:

def example(arg_1, arg_2, *args, **kwargs):
...

在使用位置参数与命名关键字参数以及*args**kwargs一起工作时,您的函数看起来像这样:

def example2(arg_1, arg_2, *args, kw_1="shark", kw_2="blobfish", **kwargs):
...

在创建函数时,保持参数的顺序是很重要的,以避免在Python代码中收到语法错误。

在函数调用中使用 *args 和 **kwargs

我们也可以使用*args**kwargs将参数传递给函数。

首先,让我们看一个使用*args的示例。

some_args.py

def some_args(arg_1, arg_2, arg_3):
    print("arg_1:", arg_1)
    print("arg_2:", arg_2)
    print("arg_3:", arg_3)

args = ("Sammy", "Casey", "Alex")
some_args(*args)

在上面的函数中,定义了三个参数:arg_1arg_2arg_3。该函数将打印出这三个参数。然后我们创建一个变量,将其设置为一个可迭代对象(在本例中是一个元组),并可以使用星号语法将该变量传递给函数。

当我们使用python some_args.py命令运行程序时,我们将收到以下输出:

arg_1: Sammy
arg_2: Casey
arg_3: Alex

我们还可以将上述程序修改为一个可迭代的列表数据类型,并使用不同的变量名。让我们还将*args语法与命名参数结合起来:

some_args.py

def some_args(arg_1, arg_2, arg_3):
    print("arg_1:", arg_1)
    print("arg_2:", arg_2)
    print("arg_3:", arg_3)

my_list = [2, 3]
some_args(1, *my_list)

如果我们运行上面的程序,它将产生以下输出:

<div class="secondary-code-label" title="输出">输出</div>arg_1: 1
arg_2: 2
arg_3: 3

类似地,关键字**kwargs参数也可用于调用一个函数。我们将设置一个变量等于一个包含3个键值对的字典(我们在这里使用kwargs,但您可以将其命名为任何名称),并将其传递给一个具有3个参数的函数:

some_kwargs.py

def some_kwargs(kwarg_1, kwarg_2, kwarg_3):
    print("kwarg_1:", kwarg_1)
    print("kwarg_2:", kwarg_2)
    print("kwarg_3:", kwarg_3)

kwargs = {"kwarg_1": "Val", "kwarg_2": "Harper", "kwarg_3": "Remy"}
some_kwargs(**kwargs)

让我们使用python some_kwargs.py命令运行上述程序:

kwarg_1: Val
kwarg_2: Harper
kwarg_3: Remy

在调用函数时,您可以使用*args**kwargs来传递参数。

结论

我们可以在函数定义中使用*args**kwargs的特殊语法,以便将可变数量的参数传递给函数。

创建接受*args**kwargs的函数最好用于您预期参数列表中的输入数量将保持相对较小的情况下。使用*args**kwargs的主要目的是提高可读性和便利性,但应该谨慎使用。

更多