【问题标题】:What does the Ellipsis object do?Ellipsis 对象有什么作用?
【发布时间】:2010-10-20 19:17:20
【问题描述】:

在闲逛命名空间时,我注意到一个名为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 链接。

标签: python ellipsis


【解决方案1】:

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

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

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

【讨论】:

  • 它现在也被 PyTorch 和其他库使用。
【解决方案2】:

来自Python documentation

这个对象通常被切片使用(见Slicings)。它不支持 特殊操作。只有一个省略号对象,名为 省略号(内置名称)。 type(Ellipsis)() 产生省略号 单身人士。

写成Ellipsis...

【讨论】:

    【解决方案3】:

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

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

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

    它的解释完全取决于实现__getitem__ 函数并在那里看到Ellipsis 对象,但它的主要(和预期)用途是在numpy 第三方库中,它添加了一个多维数组类型。由于有不止一个维度,切片变得比仅仅一个开始和停止索引更复杂;能够在多个维度上切片也很有用。例如,给定一个 4x4 数组,左上角区域将由切片 [: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],类似地,@987654335 @ 是 a[0,:,:,0](不过中间有许多冒号构成了数组中的全部维数)。

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

    >>> ...
    Ellipsis
    

    除了各种数字类型,不,我不认为它被使用。据我所知,它纯粹是为 numpy 使用而添加的,除了提供对象和相应的语法之外没有任何核心支持。那里的对象不需要这个,但是对切片的文字“...”支持却需要。

    【讨论】:

    • 它也用于存根文件中的 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]。这是同一个东西还是不同的用途?
    【解决方案4】:

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

    def will_do_something():
        ...
    

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

    def will_do_something():
        1
    

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

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

    【讨论】:

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

    您也可以在指定预期的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 实际的省略号对象。这不就是一个适应性概念的方便名称吗?
    【解决方案6】:

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

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

    请参阅this question 了解更多信息。

    【讨论】:

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

    __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
    【解决方案8】:

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

    示例 1:

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

    示例 2:

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

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

    【讨论】:

      【解决方案9】:

      正如@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
      【解决方案10】:

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

      • 在切片语法中以剩余维度表示完整切片
      • 在类型提示中仅指示类型的一部分(Callable[..., int]Tuple[str, ...]
      • 在类型存根文件中表示有一个默认值而不指定它

      可能的用途包括:

      • 作为None 是有效选项的地方的默认值
      • 作为您尚未实现的功能的内容

      【讨论】:

        【解决方案11】:

        这是等价的。

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

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

        省略号

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

        【讨论】:

          【解决方案12】:

          typer... 用于创建所需的参数:Argument 类需要一个默认值,如果你传递了...,它会在用户没有传递特定参数时报错。

          如果Ellipsis 不存在,您也可以使用None,但这将失去表达None 默认值的机会,以防万一在你的程序中。

          【讨论】:

            【解决方案13】:

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

            【讨论】:

              【解决方案14】:

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

              【讨论】:

              • 是的,这是我在自己的代码中需要的一个用例;下次我需要时会使用它。
              • 我在找这个。
              猜你喜欢
              • 1970-01-01
              • 2022-08-06
              • 1970-01-01
              • 2023-03-21
              相关资源
              最近更新 更多