version Python3.5.3
查阅 Python 文档时发现了这么一个常量 Ellipsis
文档中表述如下
Ellipsis
The same as ...
. Special value used mostly in conjunction with extended slicing syntax for user-defined container data types.
In [25]: ... is Ellipsis
Out[25]: True
有了这个常量,我们便可以定义一些有趣的东西,比如一个和 Haskell 中类似的 list
λ [1, 2]
[1,2]
:: Num t => [t]
λ [1..10]
[1,2,3,4,5,6,7,8,9,10]
:: (Enum t, Num t) => [t]
λ [1, 4 .. 10]
[1,4,7,10]
:: (Enum t, Num t) => [t]
为此我们先来看看 Python 中的序列协议 __getitem__
In [1]: class Seq(object):
...: def __getitem__(self, key):
...: return key
...:
In [2]: seq = Seq()
In [3]: seq[1, 2, 3, 4, 5]
Out[3]: (1, 2, 3, 4, 5)
In [4]: seq[1:2]
Out[4]: slice(1, 2, None)
In [5]: seq[1:10:2]
Out[5]: slice(1, 10, 2)
In [6]: seq[3, 1:10:2]
Out[6]: (3, slice(1, 10, 2))
我们可以看出,传入的是一个 tuple
类型,如果有切片操作的话,则对应一个 slice
对象
知道这点便好办了,至于无穷 list
我们可以使用 generator
来解决
class InfiniteSeq(object):
def __getitem__(self, items):
if isinstance(items, tuple):
index = 0
while index < len(items):
if items[index] is Ellipsis:
end = items[index+1] if index+1 < len(items) else float('INF')
if index > 1:
step = items[index-1] - items[index-2]
else:
step = 1 if end > items[index-1] else -1
value = items[index-1] + step
while (step > 0 and value <= end) or (step < 0 and value >= end):
yield value
value = value + step
index = index + 1
else:
yield items[index]
index = index + 1
else:
raise SyntaxError
测试结果
In [109]: seq = InfiniteSeq()
In [110]: list(seq[1, 2, 3, 4, 5])
Out[110]: [1, 2, 3, 4, 5]
In [111]: list(seq[1, ..., 5])
Out[111]: [1, 2, 3, 4, 5]
In [112]: list(seq[1, 3, ..., 7])
Out[112]: [1, 3, 5, 7]
In [113]: list(seq[1, 3, ..., 8])
Out[113]: [1, 3, 5, 7]
In [114]: list(seq[1, 3, ..., 9])
Out[114]: [1, 3, 5, 7, 9]
In [115]: list(seq[10, 1, 3, ..., 9, 12])
Out[115]: [10, 1, 3, 5, 7, 9, 12]
In [116]: list(seq[10, ..., 1])
Out[116]: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
In [117]: list(seq[10, 8, ..., 0])
Out[117]: [10, 8, 6, 4, 2, 0]
In [118]: for i in seq[1, ...]:
...: print(i)
...: if i > 5:
...: break
...:
1
2
3
4
5
6
Update 2017.05.06:
注 Numpy
在多维数组切片时有用到这个常量。比如 x
是一个四维数组,则 x[i, ...]
等价于 x[i, :, :, :]