如果您喜欢 Pythonic,我认为1:3,6,8:10,16
这是一个更好的选择,因为x:y
它是索引范围的标准表示法,并且语法允许您在对象上使用这种表示法。注意调用
z[1:3,6,8:10,16]
被翻译成
z.__getitem__((slice(1, 3, None), 6, slice(8, 10, None), 16))
即使这是一个TypeError
ifz
是一个内置容器,您也可以自由地创建将返回一些合理的类,例如 NumPy 的数组。
您也可能会说,按照惯例5:
并:5
表示无限索引范围(这有点牵强,因为 Python 没有带有负索引或无限大正索引的内置类型)。
这是解析器(一个漂亮的单行代码,有slice(16, None, None)
如下所述的故障):
def parse(s):
return [slice(*map(int, x.split(':'))) for x in s.split(',')]
然而,有一个陷阱:8:10
根据定义,只包括索引 8 和 9——没有上限。如果这对您的目的来说是不可接受的,那么您当然需要一种不同的格式并且1-3,6,8-10,16
对我来说看起来不错。然后解析器将是
def myslice(start, stop=None, step=None):
return slice(start, (stop if stop is not None else start) + 1, step)
def parse(s):
return [myslice(*map(int, x.split('-'))) for x in s.split(',')]
更新:这是组合格式的完整解析器:
from sys import maxsize as INF
def indices(s: 'string with indices list') -> 'indices generator':
for x in s.split(','):
splitter = ':' if (':' in x) or (x[0] == '-') else '-'
ix = x.split(splitter)
start = int(ix[0]) if ix[0] is not '' else -INF
if len(ix) == 1:
stop = start + 1
else:
stop = int(ix[1]) if ix[1] is not '' else INF
step = int(ix[2]) if len(ix) > 2 else 1
for y in range(start, stop + (splitter == '-'), step):
yield y
这也处理负数,所以
print(list(indices('-5, 1:3, 6, 8:15:2, 20-25, 18')))
印刷
[-5, 1, 2, 6, 7, 8, 10, 12, 14, 20, 21, 22, 23, 24, 25, 18, 19]
另一种选择是使用...
(Python 将其识别为内置常量 Ellipsis,因此您可以z[...]
根据需要调用),但我认为1,...,3,6, 8,...,10,16
可读性较差。