题
我想从字符串创建一个切片对象;现在唯一的方法似乎是通过繁琐的 eval 语句
class getslice:
def __getitem__(self, idx): return idx[0]
eval("getslice()[%s, 1]" %(":-1"))
提前致谢。
编辑: :抱歉,如果原来的提示不清楚,本例中输入的是“:-1”。重点是解析字符串。Ignacio Vazquez-Abrams 的回应至少解决了问题(并且似乎也适用于反向索引),但我认为我上面的解决方案即使在概念上不干净,仍然更清晰(并且如果 Python 改变了切片语法,它将正常工作)。
解决方案
slice(*[{True: lambda n: None, False: int}[x == ''](x) for x in (mystring.split(':') + ['', '', ''])[:3]])
其他提示
如果你想有一个片断对象,你为什么不只是一个实例?
s = slice(start, stop, step)
什么是你的“从字符串创建它”,意思?
slice(*map(lambda x: int(x.strip()) if x.strip() else None, mystring.split(':')))
在请求时,把它从注释部分的
我会在这里结束,因为我想我的脚本接受蟒蛇般拼接参数,并将它呈现为一个整数列表,我似乎喜欢它回答了OP的问题的功能做到了:
# create a slice object from a string
def get_slice_obj(slicearg):
slice_ints = tuple([ int(n) for n in slicearg.split(':') ])
return apply(slice, slice_ints)
def ints_from_slicearg(slicearg):
slice_obj = get_slice_obj(slicearg)
return(range(slice_obj.start or 0, slice_obj.stop or -1, slice_obj.step or 1))
for t in ['1', '1:3', '4:9:2']:
print t, "=>", ints_from_slicearg(t)
输出:
1 => [0]
1:3 => [1, 2]
4:9:2 => [4, 6, 8]
下面是另一种方法(只是别人的一个整合张贴在这里):
def make_slice(expr):
def to_piece(s):
return s and int(s) or None
pieces = map(to_piece, expr.split(':'))
if len(pieces) == 1:
return slice(pieces[0], pieces[0] + 1)
else:
return slice(*pieces)
实施例的用法:
In [1]: make_slice(':')
Out[1]: slice(None, None, None)
In [2]: make_slice(':-2')
Out[2]: slice(None, -2, None)
In [3]: x = [1, 2, 3]
In [4]: x[make_slice('::-1')]
Out[4]: [3, 2, 1]
这伊格纳西奥巴斯克斯 - 拉姆斯的单行是短但几乎可读并用slice
不一致处理一个数。此尝试分析它在一个清洁的方式。
def parse_slice(value):
"""
Parses a `slice()` from string, like `start:stop:step`.
"""
if value:
parts = value.split(':')
if len(parts) == 1:
# slice(stop)
parts = [None, parts[0]]
# else: slice(start, stop[, step])
else:
# slice()
parts = []
return slice(*[int(p) if p else None for p in parts])
# unit tests:
try:
assert parse_slice('')
assert False, 'It should raise TypeError'
except TypeError:
pass
assert parse_slice('2') == slice(2)
assert parse_slice('2:3') == slice(2, 3)
assert parse_slice(':3') == slice(None, 3)
assert parse_slice(':') == slice(None, None)
assert parse_slice('2:') == slice(2, None)
assert parse_slice('2:3:4') == slice(2, 3, 4)
assert parse_slice(':3:4') == slice(None, 3, 4)
assert parse_slice('2::4') == slice(2, None, 4)
assert parse_slice('2:3:') == slice(2, 3, None)
assert parse_slice('::4') == slice(None, None, 4)
assert parse_slice('2::') == slice(2, None, None)
assert parse_slice('::') == slice(None, None, None)
assert parse_slice('-12:-13:-14') == slice(-12, -13, -14)
assert parse_slice('2:3:-4') == slice(2, 3, -4)
try:
parse_slice('1:2:3:4')
assert False, 'It should raise TypeError'
except TypeError:
pass
起草了精心解析下面的函数:
def parse_slice(v: Text):
"""
Parses text like python "slice" expression (ie ``-10::2``).
:param v:
the slice expression or a lone integer
:return:
- None if input is None/empty
- a ``slice()`` instance (even if input a lone numbrt)
:raise ValueError:
input non-empty but invalid syntax
"""
orig_v = v
v = v and v.strip()
if not v:
return
try:
if ':' not in v:
## A lone number given.
v = int(v)
return slice(v, v + 1)
return slice(*map(lambda x: int(x.strip()) if x.strip() else None,
v.split(':')))
except Exception:
pass
## An alternative is to return `slice(None)` here.
raise trt.TraitError("Syntax-error in '%s' slice!" % orig_v)
怎么回合这(对于简单的非空片的间隔):
sliceStr = "3:8"
mySlice = slice( *map(int, sliceStr.split(':') ) )
切片对象通常使用下标表示法创建,该表示法内部使用 slice(),如 slice() 文档. 。你想做的是:
your_string[start:end]
从 蟒蛇教程:
字符串可以加下标(索引);像在C中一样,字符串的第一个字符具有下标(索引)0。没有单独的字符类型;字符只是一串大小。像图标中一样,可以用切片表示法指定子字符串:两个索引被结肠隔开。
>>> word = 'Help' + 'A'
>>> word[4]
'A'
>>> word[0:2]
'He'
>>> word[2:4]
'lp'
切片索引有有用的默认值;省略的第一个索引默认值为零,省略的第二个索引默认值为所切片的字符串大小。
>>> word[:2] # The first two characters
'He'
>>> word[2:] # Everything except the first two characters
'lpA'
我的解决方案来分析从字符串numpy的风格高级索引:我要点。 尽管这是一个老帖子,它是唯一一个我可以找到关于这个话题。希望它帮助。
当的建议,我粘贴这里的代码,它可以是一点点长...该代码使用量(假设a
是阵列状物体):a[parse_slice('1')]
给出a[1]
; a[parse_slice('2:,-1')]
给a[2:,-1]
;等
import re
SLICE_TEMPLATES = [
('s', r'(?P<i>[+-]?\d+)'),
('sp', r'\((?P<i>[+-]?\d+)\)'),
('a', r'::?'),
('ri-', r'(?P<i>[+-]?\d+)::?'),
('ri-k', r'(?P<i>[+-]?\d+)::(?P<k>[+-]?\d+)'),
('r-j', r':(?P<j>[+-]?\d+):?'),
('r-jk', r':(?P<j>[+-]?\d+):(?P<k>[+-]?\d+)'),
('rij', r'(?P<i>[+-]?\d+):(?P<j>[+-]?\d+):?'),
('rijk', r'(?P<i>[+-]?\d+):(?P<j>[+-]?\d+):(?P<k>[+-]?\d+)'),
('r--k', r'::(?P<k>[+-]?\d+)'),
('l', r'\.\.\.'),
('eb', r'\[(?P<e>[+-]?\d+(,[+-]?\d+)*,?)\]'),
('ep', r'\((?P<e>[+-]?\d+(,[+-]?\d+)+,?)\)'),
('ep1', r'\((?P<e>[+-]?\d+,)\)'),
]
SLICE_TEMPLATES = [(k, re.compile(v)) for k, v in SLICE_TEMPLATES]
def tokenize_slice_groups(string):
# tokenize groups
groups = []
sbuf = []
expecting = {'(': ')', '[': ']'}
pbbuf = []
LEGAL_CHARS = '0123456789()[]+-:.'
WHITESPACE_CHARS = ' \t'
for c in string:
if c in WHITESPACE_CHARS:
pass
elif c == ',':
if len(pbbuf) not in (0, 2):
sbuf.append(c)
else:
groups.append(''.join(sbuf))
sbuf.clear()
pbbuf.clear()
elif c in LEGAL_CHARS:
sbuf.append(c)
if c in '([':
if pbbuf:
raise ValueError('too many brackets in axis {}'.format(
len(groups)))
pbbuf.append(c)
elif c in ')]':
if not pbbuf:
raise ValueError('brackets not match in axis {}'.format(
len(groups)))
if c != expecting[pbbuf[0]]:
raise ValueError('brackets not match in axis {}'.format(
len(groups)))
pbbuf.append(c)
else:
raise ValueError('illegal char `{}\''.format(c))
groups.append(''.join(sbuf))
return groups
def parse_slice_group(string):
for name, tem in SLICE_TEMPLATES:
matched = tem.fullmatch(string)
if matched:
if name[0] == 's':
return int(matched.group('i'))
if name[0] == 'a':
return slice(None, None, None)
if name[0] == 'r':
i, j, k = None, None, None
if 'i' in name:
i = int(matched.group('i'))
if 'j' in name:
j = int(matched.group('j'))
if 'k' in name:
k = int(matched.group('k'))
return slice(i, j, k)
if name[0] == 'l':
return ...
# if name[0] == 'e'
return list(map(int, filter(None, matched.group('e').split(','))))
raise ValueError('illegal group "{}"'.format(string))
def parse_slice(string):
groups = tokenize_slice_groups(string)
if groups == ['']:
raise ValueError('index must not be empty')
if groups and groups[-1] == '':
del groups[-1]
index = tuple(map(parse_slice_group, groups))
if index.count(...) > 1:
raise ValueError('ellipsis may occur at most once')
return index