6 个 Python 中使用 * 和 ** 的场景

通过示例解释

Szabolcs Toth在Unsplash上的照片

如果你曾经阅读过Python库的文档,那么你一定会注意到在几个地方使用了*或**。

但是,它们(*和**)是做什么用的呢?

我们将学习7个使用*和**的例子,包括你在文档中注意到的案例。

使用示例来解释这些用例是最好的,所以让我们直接开始吧。

1. 使用可迭代对象调用函数

假设你定义了一个函数,它需要5个位置参数,将它们相加并返回总和。

# 定义函数def calculate_sum(a, b, c, d, e):    return a + b + c + d + e# 调用函数result = calculate_sum(1, 4, 3, 2, 6)print(result)16

如果作为参数传递给函数的值存储在一个可迭代对象(例如列表)中,你可以直接使用列表调用函数,但是你需要使用*,如下所示:

# 调用函数numbers = [1, 4, 3, 2, 6]calculate_sum(*numbers)print(result)16

如果尝试像calculate_sum(numbers)这样调用函数,Python会报错,引发TypeError。这里*的作用是解包可迭代对象中的值,有时也称为参数解包。

需要注意的是,numbers列表中的值的数量必须等于函数所需的参数数量,这在这种情况下是5。否则,我们会得到TypeError

2. 使用字典调用函数

这个用例与前一个用例类似。在前一个示例中,函数只有位置参数。对于带有关键字参数的函数,我们仍然可以进行参数解包,但是使用**而不是*。

# 定义函数def calculate_mass(density, length=1, width=1, height=1):    return density * length * width * height# 调用函数density = 20mass = calculate_mass(density, 2, 3, 5)print(mass)600

该函数使用密度、长度、宽度和高度计算物体的质量。假设这些测量值存储在Python字典中。我们可以直接使用字典调用函数,如下所示:

# 调用函数density = 20measures = {    "length": 2,    "width": 3,    "height": 5}calculate_mass(density, **measures)600

与第一个示例类似,如果我们尝试像calculate_mass(density, measures)这样调用它,我们会得到TypeError。这是另一个参数解包的示例。

3. 定义一个带有任意数量位置参数的函数

你定义了一个函数,它将给定的值相加,但是你不想对传递的值的数量施加限制。相反,你希望它是动态的,并且可以总结任意数量的给定值。

下面是我们如何定义这个函数:

# 定义函数def calculate_sum(*args):    result = 0    for i in args:        result += i    return result

*args表达式将传递给函数的参数打包,允许我们使用任意数量的参数或可迭代对象调用该函数。

下面是不同调用这个函数的方法:

# 调用2个值的情况calculate_sum(3, 4)7# 调用一个列表的情况my_list = [1, 4, 5, 10, 20]calculate_sum(*my_list)40# 调用一个值和一个列表的情况my_list = [10, 20, 30]calculate_sum(5, *my_list)65

如果使用可迭代对象调用函数,则在调用函数时仍需要放置 *。

关于位置参数和关键字参数的说明:

位置参数仅通过名称声明。调用函数时,必须为位置参数提供值。否则,将会出现错误。

关键字参数通过名称和默认值声明。如果我们没有为关键字参数指定值,则它将取默认值。

4. 定义带有任意数量关键字参数的函数

这个与前一个用例类似,但我们将创建一个接受关键字参数的函数。

# 定义函数def greet(name, **kwargs):    greeting = f"Hello, {name}.\n"        if kwargs:        greeting += "Here are the things I know about you:\n"        for key, value in kwargs.items():            greeting += f" {key.title()}: {value}\n"        return greeting

函数通过给定名称来问候人们。如果使用关于人们的其他关键字参数调用它,则函数也会将它们打印出来。

**kwargs 表达式允许我们在调用函数时传递任意数量的关键字参数。

以下是调用此函数的不同方式:

# 仅使用名称(位置参数)调用print(greet("John"))# 输出Hello, John.# 添加一些关键字参数调用print(greet("Jane", age=34, job="doctor", hobby="chess"))# 输出Hello, Jane.Here are the things I know about you: Age: 34 Job: doctor Hobby: chess# 将一些关键字参数作为字典添加进行调用ashley = {    "age": 27,    "profession": "athlete",    "hobby": "reading"}print(greet("Ashley", **ashley))# 输出Hello, Ashley.Here are the things I know about you: Age: 27 Profession: athlete Hobby: reading

如果将关键字参数作为字典传递,则在调用函数时需要放置 **。

5. 合并字典

我们可以使用 ** 来合并字典。

ages = {    "John": 34,    "Jane": 36}new_items = {    "Matt": 28,    "Ashley": 24}ages = {**ages, **new_items}print(ages){'John': 34, 'Jane': 36, 'Matt': 28, 'Ashley': 24}

在这种情况下,使用 ages = {ages, new_items} 同样会引发 TypeError

6. 将值打包到可迭代对象中

假设我们有一个包含多个值的列表。我们想要将该列表中的一个值分配给另一个变量,并将剩余的值分配给另一个变量。当我们通过以下示例进行演示时,它将更加清晰:

first, *others = [3, 5, 1, 10, 24]print(first)print(others)# 输出3[5, 1, 10, 24]

第一个值分配给名为 first 的变量,其余的值打包到名为 others 的另一个列表中。

我们也可以像下面的示例一样使用它:

first, *others, last = [3, 5, 1, 10, 24]print(first)print(others)print(last)# 输出3[5, 1, 10]24

当使用返回多个值的函数时,这个用例可能会很有帮助。以下是一个示例:

# 定义函数def my_func(a, b, c, d, e):    sum_1 = a + b    sum_2 = a + b + c    sum_3 = a + b + c + d    sum_4 = a + b + c + d + e    return sum_1, sum_2, sum_3, sum_4# 调用函数first_sum, *other_sums = my_func(1, 3, 5, 2, 6)print(first_sum)print(other_sums)# 输出4[9, 11, 17]

my_func 函数返回一个包含 4 个值的元组。第一个值被赋值给变量 first_one,其他的值被赋值给名为 other_sums 的列表。

最后的话

正如我们所演示的例子,* 和 ** 在 Python 中非常有用。我们可以使用它们进行参数打包和解包。

它们还用于定义和调用函数,以增加更多的灵活性和多样性。

您可以成为小猪AI的会员,以解锁我所有的文章,以及小猪AI的其他内容。如果您已经是会员,请订阅,以便在我发布新文章时收到电子邮件。

感谢您的阅读。如果您有任何反馈,请告诉我。