网站搜索

探索 Python 的省略号 (...):不仅仅是语法糖


有没有想过 Python 中的三个点 (...) 是做什么用的?了解这个强大的运算符如何简化您的代码!

Python 是一种以其强大功能而闻名的语言,它有一些隐藏的瑰宝,但并不总是得到应有的重视。根据主题,我们声称省略号就是这样的功能之一,其用途是程序员通常不知道的。简单来说,省略号是一个三点符号,用作占位符,用于突出显示未完成的代码或计划未来工作的区域。省略号使多维数组的切片变得更容易,并且在类型提示中很有用。因此,我们可以说省略号是一个可以改进代码的工具,使代码更有条理,同时简化复杂的操作。

您不需要导入省略号即可使用它。现在让我们更深入地了解省略号所提供的内容。

1. 省略号作为占位符

大多数在英语中,三个点表示继续或表示跳过的部分。同样,在Python中,省略号可以充当迄今为止尚未实现的代码的载体。当您构造函数、类甚至整个模块时,这种方法特别有用,允许您将部分代码留空而不会导致语法错误。
例如,如果您正在设计一个程序并且知道代码结构但尚未编写所有逻辑,则可以使用 ... 来保存代码最终所在的位置:

def classify():
...

在这种情况下,省略号就像一个“待办事项”标记,表明还有更多工作要做。与 pass 不同,pass 的作用类似于无操作占位符,使用 ...(省略号)表示函数故意不完整。

2. 多维数组切片中的省略号

Python 中的省略运算符是数组切片的一个有价值的工具,特别是在像 NumPy 这样处理多维数组可能会变得复杂的库中。考虑一个 3D 数组 arr,您想要选择前两个维度上的所有元素,同时检索最后一个维度索引 0 处的元素。使用省略号运算符,您可以通过以下方式执行此操作:

import numpy as np

# Create a 3D array
arr = np.arange(27).reshape(3, 3, 3)

# Select all elements along the first two dimensions and only index 0 of the last dimension
result = arr[..., 0]
print(result)
Output
[[ 0  3  6]
 [ 9 12 15]
 [18 21 24]]

arr[..., 0] 选择前两个维度上的所有元素,同时仅关注第三个维度中的索引 0。这种方法可以提高高维数据操作的效率,并在处理大型数据集时提高代码清晰度。

3. 默认参数值中的省略号

省略号 (...) 还可以用作 Python 函数中的唯一默认参数值,当 None 可以是有效参数时,提供了一个有用的替代方案。通过使用 ... 作为默认值,您可以清楚地区分未提供参数的情况和故意将 None 作为值传递的情况。

让我们通过一个例子来理解它:

def greet(name="Guest", greeting=...):
    if greeting is ...:
        greeting = "Hello"  # Default greeting if none provided
    print(f"{greeting}, {name}!")

# Testing different cases
greet("Alice")                 # Uses default greeting: "Hello, Alice!"
greet("Bob", greeting="Hi")    # Custom greeting: "Hi, Bob!"
greet("Charlie", greeting=None)

# Outputs: "None, Charlie!" (explicitly setting greeting to None)

在这个例子中:

  • 如果未提供问候语,则默认为“Hello”。
  • 如果提供了特定的问候语(例如“Hi”),该函数将使用该问候语而不是默认的问候语。
  • 如果greeting=None,则显示“None,{name}!”,表明 None 是有意传递的,与使用默认值不同。

4. 省略号作为类型提示

省略号 (...) 可以用作类型提示,特别是在某些上下文中,您想要指示可能存在更多值或某些内容具有未完全指定的变量结构。以下是我们将要讨论的省略号作为类型提示的两种不同用法:

对于未知长度的元组

类型提示用于表示灵活或具有未指定特征的元素。想象一下,如果您想创建一个名为grocery_list 的变量,它是一个字符串元组,但您不知道该元组中有多少个字符串。省略号确保所有元素都是字符串,同时允许元素数量变化。

Code Example:
from typing import Tuple

# Allowed:
grocery_list: Tuple[str, ...] = ("apples", "bread", "milk", "eggs", "butter")
grocery_list = ("apples",)  # A tuple with a single string is allowed
grocery_list = ()  # An empty tuple is allowed

# Not allowed:
grocery_list = (1, "bread") 
grocery_list = ["apples", "bread"] 
grocery_list = ("apples", 2.5) 

# Function to print each item in the grocery list
def print_grocery_items(items: Tuple[str, ...]) -> None:
    for item in items:
        print(f"- {item}")

# Call the function with our grocery list
print_grocery_items(grocery_list)

grocery_list: Tuple[str, ...]=("apples", "bread") 这样的变量定义是有效的,因为两个元素都是指定类型,而像 ( 1, "bread") 或列表而不是元组 ["apples", "bread"] 是不允许的。

对于具有灵活参数的可调用对象

当参数的数量和类型未知时,可以在可调用函数的类型提示中使用省略号。有时,您可能需要将一个函数传递给另一个函数,而不知道该函数的参数是什么。因此,省略号可用于表明该函数可以采用任意数量的任意类型的参数。

Code Example:
from typing import Callable

# A function that takes one number and returns it doubled
def double_value(x: int) -> int:
    return x * 2

# A function that takes two numbers and returns their sum
def add_values(x: int, y: int) -> int:
    return x + y

# A function that takes an integer, a callable, and optional extra arguments
def apply_action(value: int, action: Callable[..., int], *args: int) -> int:
    return action(value, *args)

# Allowed:
print(apply_action(5, double_value))  # Calls double_value(5), which results in 10
print(apply_action(5, add_values, 3))  # Calls add_values(5, 3), which results in 8

# Not Allowed:
apply_action(5, 3)
apply_action(5, double_value, "extra") 

在上面的例子中,

  • 函数 apply_action 接受一个整数(值)、一个可调用的(操作)和可选的附加参数 (*args)。
  • 类型提示 Callable[..., int] 表示可调用操作可以采用任意数量、任意类型的参数,但它必须返回一个 int。
  • 由于类型提示中的省略号 (...),apply_action 函数可以处理 double_value 和 add_values 函数的两种情况。
  • 不起作用的示例强调可调用对象必须是函数,并且额外的参数必须与函数的预期输入类型匹配。

这保持了类型的一致性,同时为传递给可调用的参数提供了灵活性。

总结

综上所述,Python 中的省略号(...)往往是一个被低估的功能,它可以提高编码效率。通过将省略号集成到您的编码工具包中,您可以编写更清晰、更有组织的代码。