可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'd like to create a slice object from a string; right now the only way seems through a cumbersome hacky eval statement
class getslice:
def __getitem__(self, idx): return idx[0]
eval("getslice()[%s, 1]" %(":-1"))
thanks in advance.
Edit: Sorry if the original prompt was not clear, the input in this case was ":-1". The point was to parse the string. Ignacio Vazquez-Abrams's response at least solved the problem (and seems to work with reverse indexing as well), but I think my solution above is still more clear if not conceptually clean (and will work correctly if Python ever changes slicing syntax).
回答1:
slice(*[{True: lambda n: None, False: int}[x == ''](x) for x in (mystring.split(':') + ['', '', ''])[:3]])
回答2:
If you want a slice object, why don't you just instantiate one?
s = slice(start, stop, step)
What are you meaning by "creating it from a string"?
回答3:
slice(*map(lambda x: int(x.strip()) if x.strip() else None, mystring.split(':')))
On request, took it out of comment section.
回答4:
I end up here because I wanted my script to accept a python-like splice argument and render it into a list of integers, I did it with a function that seems like it answers the OP's question:
# 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)
Output:
1 => [0]
1:3 => [1, 2]
4:9:2 => [4, 6, 8]
回答5:
Here's another method (just a consolidation of the others posted here):
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)
Example usages:
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]
回答6:
The one-liner from Ignacio Vazquez-Abrams is short but hardly readable and handles a single number inconsistently with slice
. This tries to parse it in a cleaner way.
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
回答7:
Based on @pprzemak drafted the following function for elaborate parsing:
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)
回答8:
How 'bout this (for simple non empty slice intervals) :
sliceStr = "3:8"
mySlice = slice( *map(int, sliceStr.split(':') ) )
回答9:
A slice object is usually created using subscript notation, this notation uses slice() internally, as stated on the slice() documentation. What you want to do is:
your_string[start:end]
From the python tutorial:
Strings can be subscripted (indexed);
like in C, the first character of a
string has subscript (index) 0. There
is no separate character type; a
character is simply a string of size
one. Like in Icon, substrings can be
specified with the slice notation: two
indices separated by a colon.
>>> word = 'Help' + 'A'
>>> word[4]
'A'
>>> word[0:2]
'He'
>>> word[2:4]
'lp'
Slice indices have useful defaults; an
omitted first index defaults to zero,
an omitted second index defaults to
the size of the string being sliced.
>>> word[:2] # The first two characters
'He'
>>> word[2:] # Everything except the first two characters
'lpA'