ChatGPT解决这个技术问题 Extra ChatGPT

Ellipsis 对象有什么作用?

在闲逛命名空间时,我注意到一个名为 Ellipsis 的奇怪对象,它似乎并没有做任何特别的事情,但它是一个全局可用的内置函数。

经过搜索,我发现它被 Numpy 和 Scipy 用于切片语法的一些晦涩变体中......但几乎没有别的。

是否将此对象添加到语言中专门用于支持 Numpy + Scipy?省略号有任何通用含义或用途吗?

D:\workspace\numpy>python
Python 2.4.4 (#71, Oct 18 2006, 08:34:43) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> Ellipsis
Ellipsis
我发现它是这样的:我输入 x=[];x.append(x);print(x),看看它如何处理字符串化循环对象。它返回 [[...]]。我想“我想知道如果我输入 [[...]] 会发生什么?我猜它会抛出一个语法错误。相反,它返回 [[Ellipsis]]。Python 太奇怪了。随后的谷歌搜索把我带到了这个页面。
请注意,递归 repr 中的 ... 只是一个占位符,与 Ellipsis 无关
完全侧面说明,导入中的三点表示“从两个包向上导入”。
@croq stackoverflow.com/q/32395926/2988730stackoverflow.com/q/1054271/2988730。这两个人应该解释一切,并在答案中提供正确的文档和 PEP 链接。

A
Augustin

这在最近的另一个 question 中出现。我将从那里详细说明我的 answer

Ellipsis 是一个可以以切片表示法出现的对象。例如:

myList[1:2, ..., 0]

它的解释完全取决于实现 __getitem__ 函数并在那里看到 Ellipsis 对象的任何东西,但它的主要(和预期)用途是在 numpy 第三方库中,它添加了一个多维数组类型。由于有多个维度,切片变得比仅仅一个开始和停止索引更复杂;能够在多个维度上切片也很有用。例如,给定一个 4 × 4 数组,左上角区域将由切片 [:2, :2] 定义:

>>> a
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12],
       [13, 14, 15, 16]])

>>> a[:2, :2]  # top left
array([[1, 2],
       [5, 6]])

进一步扩展这一点,省略号在这里用于指示未指定的其余数组维度的占位符。将其视为在其放置的间隙中指示所有维度的完整切片 [:],因此对于 3d 数组,a[..., 0]a[:, :, 0] 相同,对于 4d a[:, :, :, 0],类似地,a[0, ..., 0]a[0, :, :, 0](中间有许多冒号构成了数组中的全部维数)。

有趣的是,在 python3 中,省略号文字 (...) 可以在切片语法之外使用,因此您实际上可以编写:

>>> ...
Ellipsis

编辑:省略号也用于标准库 typing 模块:例如 Callable[..., int] 表示返回 int 而不指定签名的可调用对象,或 tuple[str, ...] 表示字符串的可变长度同质元组。


它也用于存根文件中的 PEP484 类型提示
以防万一有人好奇:它也用于标准库 typing 模块中:例如 Callable[..., int] 表示返回 int 而不指定签名的可调用对象,或 Tuple[str, ...] 表示可变长度同质元组的字符串。
仅供参考,FastAPI 框架(适用于 python 3.6+)也(现在)使用它。 fastapi.tiangolo.com/tutorial/query-params-str-validations
@ArtOfWarfare 你是完全正确的,这是来自口头上说“省略号”而不是在句子之间拖尾的人。
我找到了这个。当您在列表中进行自引用(循环引用)时,它似乎会出现:a = [1, 2]; a[0] = a; print(a) 给出 [[...], 2]。这是同一件事还是不同的用途?
t
tzot

在 Python 3 中,您可以¹使用省略号文字 ... 作为尚未编写的代码的“nop”占位符:

def will_do_something():
    ...

不是魔法;可以使用任何表达式代替 ...,例如:

def will_do_something():
    1

(不能使用“sanctioned”这个词,但我可以说这个用法是 Guido 的not outrightly rejected。)

¹ 'can' not in {'must', 'should'}


在半惯例中,我经常看到 ... 用于人们想要表示他们打算稍后填写的内容(“待办事项”空块),而 pass 表示打算没有代码的块。
Python 还具有 NotImplemented 文字,当您希望不完整的函数返回有意义的内容时(而不是示例中的 None),这很有用。 (另一个用例:Implementing arithmetic operations
@zvyn 这不是文字。这只是一个名字。例如 NotImplemented = 'something_else' 是有效的 Python,但 ... = 'something_else' 是语法错误。
@zvyn 如果在导入该模块时发生异常怎么办? :)
@zvyn NotImplemented 不是 None 的替代品。它的使用范围相当狭窄。请参阅文档 here
p
phoenix

从 Python 3.5 和 PEP484 开始,文字省略号用于在使用 typing 模块时向静态类型检查器表示某些类型。

示例 1:

可以使用一种类型和省略号来表示任意长度的同质元组,例如 Tuple[int, ...]

示例 2:

通过用文字省略号(三个点)代替参数列表,可以在不指定调用签名的情况下声明可调用的返回类型:

def partial(func: Callable[..., str], *args) -> Callable[..., str]:
    # Body

M
Matthew D. Scholefield

总结其他人所说的,从 Python 3 开始,Ellipsis 本质上是另一个类似于 None 的单例常量,但没有特定的预期用途。现有用途包括:

在切片语法中表示剩余维度中的完整切片

在类型提示中仅指示类型的一部分(Callable[..., int] 或 Tuple[str, ...])

在类型存根文件中表示有一个默认值而不指定它

可能的用途可能包括:

作为 None 是有效选项的地方的默认值

作为您尚未实现的功能的内容


“作为 None 是有效选项的地方的默认值”是
我不会使用 ... 作为默认值。 None 至少传达了“没有传递值”的语义; ... 没有。备用标记通常是 object 或自定义类的特制实例,旨在使用 is 进行测试。例如,参见 dataclasses module,它以这种方式定义了几个自定义标记。
“作为 None 是有效选项的地方的默认值”->你在谈论类型提示或存根文件吗?你能详细说明一下吗?如您所知,在普通代码中,EllipsisNone 不同。
我认为他们的意思是在处理 None 值的函数中使用 ... 作为参数的默认值(表示没有真正传递给该参数)。 def function(param1 = 5, param2 = ...): if not param2 is Ellipsis: #do something else: #do something else - 例如,此函数可能与传入的 None 值有关。因此我们在这里使用 ...Ellipsis 作为默认值,这是合理的,因为该对象没有实际用途(至少不适合我)
C
Chiggs

您还可以在指定预期的 doctest 输出时使用省略号:

class MyClass(object):
    """Example of a doctest Ellipsis

    >>> thing = MyClass()
    >>> # Match <class '__main__.MyClass'> and <class '%(module).MyClass'>
    >>> type(thing)           # doctest:+ELLIPSIS
    <class '....MyClass'>
    """
    pass

但这真的涉及 Ellipsis 对象吗?它不只是 doctest 解析器/匹配器的一个特性吗?
@akaihola 我会说确实如此,如 doctest.ELLIPSIS 中所述。我希望 ... 的大多数(如果不是全部)使用都是句法,而不是 use 实际的 Ellipsis 对象。它真的只是一个适应性概念的方便名称吗?
这只是指文本中的省略号,而不是 Python 文字 ...
S
Simon Lieschke

Python documentation

此对象通常由切片使用(请参阅切片)。它不支持特殊操作。只有一个省略号对象,名为 Ellipsis(内置名称)。 type(Ellipsis)() 生成 Ellipsis 单例。它被写为省略号或....


C
Ciro Santilli Путлер Капут 六四事

__getitem__ 自定义类中的最小 ... 示例

在自定义类中将魔术语法 ... 传递给 [] 时,__getitem__() 会收到一个 Ellipsis 类对象。

然后该类可以对这个 Singleton 对象做任何它想做的事情。

例子:

class C(object):
    def __getitem__(self, k):
        return k

# Single argument is passed directly.
assert C()[0] == 0

# Multiple indices generate a tuple.
assert C()[0, 1] == (0, 1)

# Slice notation generates a slice object.
assert C()[1:2:3] == slice(1, 2, 3)

# Ellipsis notation generates the Ellipsis class object.
# Ellipsis is a singleton, so we can compare with `is`.
assert C()[...] is Ellipsis

# Everything mixed up.
assert C()[1, 2:3:4, ..., 6] == (1, slice(2,3,4), Ellipsis, 6)

Python 内置的 list 类选择赋予它范围的语义,当然,任何合理的用法也应该如此。

就个人而言,我只是在我的 API 中远离它,而是创建一个单独的、更明确的方法。

在 Python 3.5.2 和 2.7.12 中测试。


使用 -O 参数运行它,您的代码将始终运行;D
t
tykom

对于在大量使用 Pydantic 的代码库中工作而获得此答案的任何人:这也是 Pydantic 指示一个必需但可以设置为 None 的字段的方式,他们将其称为“required optional fields”。这也是为什么它们最终也被用于 FastAPI 的原因。


是的,这是我在自己的代码中需要的一个用例;下次我需要它时会使用它。
C
Community

您可以自己使用 Ellipsis,在像 numpy 这样的自定义切片情况下,但它在任何内置类中都没有使用。

我不知道它是否是专门为在 numpy 中使用而添加的,但我当然没有看到它在其他地方使用过。

另请参阅:How do you use the ellipsis slicing syntax in Python?


PyTorch 和其他库现在也使用它。
M
Markus Meskanen

正如@noɥʇʎԀʎzɐɹƆ 和 @phoenix 所提到的 - 您确实可以在存根文件中使用它。例如

class Foo:
    bar: Any = ...
    def __init__(self, name: str=...) -> None: ...

可以在此处找到有关如何使用此省略号的更多信息和示例https://www.python.org/dev/peps/pep-0484/#stub-files


好的,然后当我实际实例化该类并且省略号代码运行时会发生什么?
@Robert 什么都没有发生。将 if 视为 None
@Robert 存根文件,例如 module.pyi 存在用于静态类型检查,它不是可执行代码。它用于向没有它的模块添加类型信息。在这种用法def foo(bar:str=...)->str 中,它表示有一个默认值(即参数是可选的),但没有指明默认值是什么。
@Ben 简单但清晰的解释 :) 顺便说一句,上面代码中的 bar: Any = ...-> None: ... 是什么?哦,我认为 -> None: 之后的 ... 可能只是表示方法的主体?
@starriet bar: Any = ... 表示 Foo 有一个类型为 Any 的名为 bar 的成员,具有未指定的默认值。 pyi 文件通常会这样做。
C
Community

它的预期用途不应仅用于这些第 3 方模块。 Python 文档中没有正确提及它(或者我可能只是找不到),但 省略号 ... 实际上在 CPython 中至少在一个地方使用过。

它用于表示 Python 中的无限数据结构。我在玩列表时遇到了这个符号。

有关详细信息,请参阅 this question


不同的东西。这个问题询问的是 ellipsis 内置类型和 Ellipsis 对象。用省略号表示无限数据结构纯粹是为了显示,与 ellipsis 类型或 Ellipsis 对象无关。
@chys 实际上,它以一种很小的方式起作用 - Python __repr__ 字符串旨在成为有效的 Python 表达式 - 如果它不是语言中存在的省略号,那么表示将不是有效的表达式。
@Lattyware 好吧,原来的设计确实如此。它还打算使 eval(repr(a)) 目标等于 a。不幸的是,在实践中它有时是错误的,即使对于内置类型也是如此。试试这个:a=[]; a.append(a); eval(repr(a))repr(a)[[...]],在 Python 2 中是无效的表达式。(在 Python 3 中它是有效的,但是 eval 的结果有些不同,仍然违背了初衷。)
C
Community

这是等价的。

l=[..., 1,2,3]
l=[Ellipsis, 1,2,3]

... 是在 built-in constants 中定义的常量。

省略号 与省略号文字“...”相同。特殊值主要与用户定义的容器数据类型的扩展切片语法结合使用。


u
user4344

typer 中,... 用于创建必需的参数:Argument 类需要一个默认值,如果您传递 ...,如果用户未传递特定参数,它会报错。

如果 Ellipsis 不存在,您可以使用 None,但这将失去表达 None 默认值的机会,以防在您的程序中有任何意义.


I
Irrer Polterer

FastAPI 使用省略号来创建所需的参数。 https://fastapi.tiangolo.com/tutorial/query-params-str-validations/