Newbie question, list comprehension

Mark Wooding mdw at distorted.org.uk
Sun Jun 8 15:11:50 CEST 2008


Johannes Bauer <dfnsonfsduifb at gmx.de> wrote:

> import time
> localtime = time.localtime(1234567890)
> fmttime = "%04d-%02d-%02d %02d:%02d:%02d" % (localtime[0], localtime[1], 
> localtime[2], localtime[3], localtime[4], localtime[5])
> print fmttime
>
> fmttime = "%04d-%02d-%02d %02d:%02d:%02d" % ([localtime[i] for i in 
> range(0, 5)])

To reduce typing, set
 
  format = '%04d-%02d-%02d %02d:%02d:%02d'

Two problems.

  * Firstly, range(0, 5) == [0, 1, 2, 3, 4], so it's not big enough.
    Python tends to do this half-open-interval thing.  Once you get used
    to it, you'll find that it actually reduces the number of off-by-one
    errors you make.

  * Secondly, the result of a list comprehension is a list;
    (Unsurprising, really, I know.)  But the `%' operator only extracts
    multiple arguments from a tuple, so you'd need to convert:

      format % tuple(localtime[i] for i in xrange(6)]

(I've replaced range by xrange, which avoids building an intermediate
list, and the first argument to range or xrange defaults to zero
anyway.)

Another poster claimed that localtime returns a tuple.  This isn't
correct: it returns a time.struct_time, which is not a tuple as you can
tell:

  >>> '%s' % localtime
  '(2009, 2, 13, 23, 31, 30, 4, 44, 0)'

This is one of those times when Python's duck typing fails -- string
formatting really wants a tuple of arguments, and nothing else will do.

But you can slice a time.struct_time, and the result /is/ a genuine
tuple:

  >>> type(localtime[:6])
  <type 'tuple'>

which is nice:

  >>> format % localtime[:6]
  '2009-02-13 23:31:30'

But really what you wanted was probably

  >>> time.strftime('%Y-%m-%d %H:%M:%S', localtime)
  '2009-02-13 23:31:30'

-- [mdw]



More information about the Python-list mailing list