如何在Python3中使用*args和**kwargs

来自菜鸟教程
跳转至:导航、​搜索

介绍

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

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

先决条件

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

理解 *args

在 Python 中,*args 的单星号形式可用作参数,将非关键字变长参数列表发送给函数。 值得注意的是,星号 (*) 是这里的重要元素,因为 args 这个词是既定的常规习语,尽管语言没有强制执行它。

Info: 要跟随本教程中的示例代码,请通过运行 python3 命令在本地系统上打开 Python 交互式 shell。 然后,您可以通过在 >>> 提示符后添加示例来复制、粘贴或编辑示例。


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

let_multiply.py

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

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

let_multiply.py

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

multiply(5, 4)

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

python lets_multiply.py

我们将收到以下输出,表明整数 5 和 4 根据 multiply(x,y) 函数相乘:

Output20

如果稍后我们决定要乘以三个数字而不是两个数字怎么办? 如果我们尝试向函数添加一个额外的数字,如下所示,我们将收到一个错误。

let_multiply.py

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

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

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

我们基本上可以创建我们在第一个示例中展示的相同函数和代码,通过删除 xy 作为函数参数,并将它们替换为 *args

let_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)

当我们运行此代码时,我们将收到每个函数调用的产品:

Output20
90
24
900

因为我们使用 *args 来向我们的函数发送一个可变长度的参数列表,所以我们能够将任意数量的参数传递给函数调用。

使用 *args,您可以创建更灵活的代码,在您的函数中接受各种数量的非关键字参数。

了解 **kwargs

**kwargs 的双星号形式用于将关键字变长参数 dictionary 传递给函数。 同样,这两个星号 (**) 是这里的重要元素,因为 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
Output{'kwargs_3': True, 'kwargs_2': 4.5, 'kwargs_1': 'Shark'}

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

需要注意的是,创建了一个名为 kwargs 的字典,我们可以像使用其他字典一样使用它。

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

打印值.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
OutputThe value of your_name is Casey
The value of my_name is Sammy

同样,因为字典可能是无序的,所以您的输出可能首先是名称 Casey 或名称是 Sammy

现在让我们将其他参数传递给函数,以表明 **kwargs 将接受您想要包含的任何参数:

打印值.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"
        )

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

OutputThe 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_arg_3。 该函数将打印出每个参数。 然后我们创建一个设置为可迭代的变量(在本例中为 tuple),并可以使用星号语法将该变量传递给函数。

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

Outputarg_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)

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

Outputarg_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 命令运行上面的程序:

Outputkwarg_1: Val
kwarg_2: Harper
kwarg_3: Remy

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

结论

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

创建接受 *args**kwargs 的函数最适用于您希望参数列表中的输入数量保持相对较小的情况。 使用 *args**kwargs 主要是为了提供可读性和便利性,但应谨慎使用。