Creating slice notation from string

Steven D'Aprano steven at REMOVE.THIS.cybersource.com.au
Wed Sep 2 23:52:53 EDT 2009


On Wed, 02 Sep 2009 17:32:09 -0700, Bob van der Poel wrote:

> Actually, nither this or Jan's latest is working properly. I don't know
> if it's the slice() function or what (I'm using python 2.5). But:
> 
> x = [1,2,3,4,5]
> slice_string="2"
> items = [int(n) if n else None for n in slice_string.split(":")]
> [slice(*items)]
> [1, 2]

It's not clear what is input and what is output. I'm *guessing* that the 
first four lines are input and the fifth is output.

By the way, nice catch for the "else None". But why are you wrapping the 
call to slice() in a list in the fourth line?


I can't replicate your results. I get the expected results:


>>> slice_string="2"
>>> items = [int(n) if n else None for n in slice_string.split(":")]
>>> [slice(*items)]
[slice(None, 2, None)]

exactly the same as:

>>> slice(2)
slice(None, 2, None)

Testing this, I get the expected result:

>>> x = [1,2,3,4,5]
>>> x[slice(*items)]
[1, 2]

which is exactly the same if you do this:

>>> x[:2:]
[1, 2]


> not the expected:
> 
> [3]

Why would you expect that? You can't get that result from a slice based 
on 2 only. Watch:

>>> x[2::]
[3, 4, 5]
>>> x[:2:]
[1, 2]
>>> x[::2]
[1, 3, 5]

There is no slice containing *only* 2 which will give you the result you 
are asking for. You would need to do this:

>>> x[2:3]
[3]


Perhaps what you are thinking of is *indexing*:

>>> x[2]
3

but notice that the argument to list.__getitem__ is an int, not a slice, 
and the result is the item itself, not a list.

To get the behaviour you want, you need something more complicated:

def strToSlice(s):
    if ':' in s:
        items = [int(n) if n else None for n in s.split(':')]
    else:
        if s:
            n = int(s)
            items = [n, n+1]
        else:
            items = [None, None, None]
    return slice(*items)



> Things like -1 don't work either.

They do for me:


>>> slice_string="2:-2"
>>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> items = [int(n) if n else None for n in slice_string.split(":")]
>>> x[ slice(*items) ]
[3, 4, 5, 6, 7, 8]
>>> x[2:-2]
[3, 4, 5, 6, 7, 8]




> I'm really not sure what's going on, but I suspect it's the way that
> slice() is getting filled when the slice string isn't a nice one with
> each ":" present?

I think you're confused between __getitem__ with a slice argument and 
__getitem__ with an int argument.



-- 
Steven



More information about the Python-list mailing list