Python Ellipsis对象有什么作用?

What does the Python Ellipsis object do?

在空闲地浏览命名空间时,我注意到一个奇怪的叫做"省略号"的对象,它看起来没有什么特别之处,也没有做什么特别的事情,但它是一个全局可用的内置项。

在搜索之后,我发现它被numpy和scipy用在切片语法的一些模糊变体中。但几乎没有别的。

这个对象是专门添加到语言中以支持numpy+scipy吗?省略号是否有任何一般意义或用法?

1
2
3
4
5
6
D:\workspace
umpy>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


这是最近在另一个问题中出现的。我将详细阐述我的答案:

省略号是一个可以以切片表示法显示的对象。例如:

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

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

1
2
3
4
5
6
7
8
9
>>> 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]])

在此进一步扩展,省略号用于指示未指定的其余数组维度的占位符。把它看作是表示它所放置的间隙中所有尺寸的全片[:],所以对于一个三维阵列,a[...,0]a[:,:,0]相同,对于4d阵列,a[:,:,:,0]也一样,a[0,...,0]a[0,:,:,0](中间有许多冒号组成阵列中的全部尺寸)。

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

1
2
>>> ...
Ellipsis

除了各种数字类型之外,不,我认为它没有被使用。据我所知,它是纯粹为numpy使用而添加的,除了提供对象和相应的语法之外,它没有核心支持。在那里的对象不需要这样做,但是对切片的文本"…"支持确实需要这样做。


在python 3中,可以将省略号文字...用作代码的"nop"占位符:

1
2
def will_do_something():
    ...

这不是魔术;任何表达式都可以代替...,例如:

1
2
def will_do_something():
    1

(不能使用"已批准"这个词,但我可以说,这个用法并没有被guido彻底拒绝。)


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

例1:

Arbitrary-length homogeneous tuples can be expressed using one type and ellipsis, for example Tuple[int, ...]

例2:

It is possible to declare the return type of a callable without specifying the call signature by substituting a literal ellipsis (three dots) for the list of arguments:

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

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

1
2
3
4
5
6
7
8
9
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


从python文档中:

This object is used by extended slice
notation (see the Python Reference
Manual). It supports no special
operations. There is exactly one
ellipsis object, named Ellipsis (a
built-in name).


总结其他人所说的,对于python 3,省略号本质上是另一个与None相似的单例常量,但没有特定的用途。现有用途包括:

    百万千克1在切片语法中表示剩余维度中的整个切片百万千克1百万千克1在只表示一个类型的一部分(Callable[..., int]Tuple[str, ...]的类型中)百万千克1百万千克1在类型stub文件中,指示有一个默认值而不指定它百万千克1

可能的用途包括:

    百万千克1作为None是有效选项的地方的默认值百万千克1百万千克1作为尚未实现的函数的内容百万千克1


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

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

另请参见:如何在Python中使用省略号切片语法?


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

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

然后,类可以用这个singleton对象做它想做的任何事情。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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中测试。


如@no所述???????Z????和@phoenix-您确实可以在存根文件中使用它。例如

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

有关如何使用此省略号的更多信息和示例,请参阅:https://www.python.org/dev/peps/pep-0484/存根文件


其预期用途不应仅用于这些第三方模块。在python文档中没有正确地提到它(或者我只是找不到),但是省略号...至少在一个地方实际用于cpython。

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

有关详细信息,请参阅此问题。