slicing (was Re: c enum - how to do this in python?)

Alex Martelli aleax at aleax.it
Sat Feb 22 16:34:49 CET 2003


Anna wrote:
   ...
>> Python 2.3 is not yet recommended for production use, being an alpha
>> release.  It does have a few neat things such as this one (and sets and
>> enumerate and itertools) and is faster than 2.2, so for play/study
>> purposes downloading it and installing it might be fun, but be sure to
>> keep a 2.2.2 around for "production use"!-)
> 
> Sets? So I can write "dogs is dogs and cats is dogs but them turtles is

<blink> not in Python you can't ('is' and 'and' are operators,
however 'but' isn't...;-).

> insects" in Python? Kewl! Hmmm - now I gotta figure out how to put two
> different versions of Python on my box without one overwriting the
> other... and figure out how to tell it which one to call. Ohboy - new
> challenges...

Normally there is no risk of overwriting per se, given they're
different releases, 2.2 vs 2.3.  On Windows, in a default install, 
the two versions will be in C:\Python22 and c:\Python23 respectively;
on Linux, again with a default install, /usr/local/lib/python2.2
and /usr/local/lib/python2.3 plus executables in /usr/local/bin
named, again, python2.2 and python2.3.

The problem, indeed, is "how to tell" your system which version
to call.  On Windows, a key issue is what's in your environment
variable $PATH -- if C:\Python2.2 is there, or C:\Python2.3.  But
there are a few other things that may need to be set, such as,
"file associations".  In general you can reinstall a version to
make sure the file associations are as needed for that version,
or save and restore pieces of the Windows Registry (dangerous).

In Linux, it basically boils down to, what's /usr/local/bin/python --
it's a link (normally a hard-link) to either python2.2 or python2.3
in the same directory.  So you can fix things with a rm and a ln
at the shell prompt.  Again there may be a few more issues, such
as, what's idle -- it will probably have a first line (shebang) of
#!/usr/local/bin/python -- so it might not work if you have the
"wrong" version of Python set as the default.

If your versions of Linux has a /usr/bin/python too (e.g., RedHat
and Mandrake do), that will remain stable (so any system tool
coded in Python should not be affected) -- and your $PATH needs
to have /usr/local/bin BEFORE /usr/bin if you want to run the
newly installed version by default rather than the system-provided
one.  But these are all basically system administration issues
(and generalize with minor differences to most Unix and BSD boxes,
even though I keep mentioning Linux in the above) rather than
Python ones.  All in all, I've grown used to having several versions
around (I often need to test what works how where) and it's not
really a big problem, with the right work habits.


>> Reversing strings with [::-1] is more or less a divertissement,
> 
> Actually, the more I play with it, the better I like it. It still looks
> wierd though... and I still want it to have a NAME. I like names. Names
> are a Good Thing. So - what's this mutant smilie called?

anyname[ <...> ] is called a SLICING of anyname if the omitted
part indicated by <...> has a colon (that omitted part is then
also known as a SLICE); it's called an EXTENDED SLICING if the
omitted part has TWO colons.

So, 'ciao'[::-1] is an extended slicing of the string literal
'ciao'.  It's just one of many possible extended slicings of
it, of course.  The general syntax is:

    container [ start : stop : step ]

where each of start, stop and step is an optional expression. When 
start is omitted it defaults to the start of sequence (for a positive
step; to the end, for a negative one); when stop is omitted it defaults 
to the other extreme (end of sequence for a positive step, start of 
sequence for a negative one); when  step is omitted it defaults to 1, 
and in that case you normally omit the second colon too, falling back 
to the more usual case of a non-extended slicing.  What most people 
(and Python) call the 'step', some of us prefer to call the 'stride',
but it IS called "step" in a Python slice object.  Because you CAN
objectify slices, in Python...:


>>> rev = slice(None, None, -1)
>>> 'ohwow'[rev]
'wowho'
>>> rev.step
-1
>>> 

but asking for rev.stride raises an AttributeError, alas;-)


Now that you know that Python DOES slicing, I suspect your next
query will be about dicing... but, for that, see standard library
module random (well, for SOME meaning of 'dice', at least!).  And,
sorry, no Julienne fries (that's Rule 6, innit?).


>> generalized slicing also has serious uses.  Say for example you want to
>> return the LAST item in a list that meets some condition.  With
>> generalized slicing in Python 2.3 it's easy:
>> 
>> def lastone(somelist, condition):
>>     for item in somelist[::-1]:
>>         if condition(item): return item
>>     raise ValueError, "No item matches the condition"
> 
> Can't you do:
> 
> def lastone(somelist, condition):
>      for item in somelist.reverse():
>          if condition(item): return item
>      raise ValueError, "No item matches the condition"
> 
> Wouldn't that do the same thing?

It would IF .reverse() returned the reversed list, but it doesn't:
it reverses the list in-place and returns None.  Whence the need
for the circumlocutions I mentioned in my previous post as being
necessary for this task in Python 2.2.


Alex





More information about the Python-list mailing list