[Python-Dev] suggestion: except in list comprehension

tomer filiba tomerfiliba at gmail.com
Mon Apr 24 22:56:37 CEST 2006


a friend of mine suggested this, and i thought i should share it with the
mailing list.
many times when you would want to use list/generator comprehensions, you
have to
fall back to the old for/append way, because of exceptions. so it may be a
good idea
to allow an exception handling mechanism in these language constructs.

since list comprehensions are expressions, an exceptions thrown inside one
means
the entire list is discarded. you may want to provide some, at least
fundamental,
error handling, like "if this item raises an exception, just ignore it", or
"terminate the
loop in that case and return whatever you got so far".

the syntax is quite simple:

"[" <expr> for <expr> in <expr> [if <cond>] [except
<exception-class-or-tuple>: <action>] "]"

where <action> is be one of "continue" or "break":
* continue would mean "ignore this item"
* break would mean "return what you got so far"

for example:

a = ["i", "fart", "in", "your", "general", 5, "direction", "you", "silly",
"english", "kniggits"]

give me every word that starts with "y", ignoring all errors
b = [x for x in a if x.startswith("y") except: continue]
# returns ["your", "you"]

or only AttributeError to be more speciifc
b = [x for x in a if x.startswith("y") except AttributeError: continue]
# returns ["your", "you"]

and with break
b = [x for x in a if x.startswith("y") except AttributeError: continue]
# returns only ["your"] -- we didn't get past the 5

in order to do something like this today, you have to resort to the old way,
b = []
for x in a:
    try:
        if x.startswith("y"):
            b.append(x)
    except ...:
         pass

which really breaks the idea behind list comprehension.

so it's true that this example i provided can be done with a more complex if
condition
(first doing hasattr), but it's not always possible, and how would you do it
if the error
occurs at the first part of the expression?

>>> y = [4, 3, 2, 1, 0, -1, -2, -3]
>>> [1.0 / x for x in y except ZeroDivisionError: break]
[0.25, 0.333, 0.5, 1.0]
>>> [1.0 / x for x in y except ZeroDivisionError: continue]
[0.25, 0.333, 0.5, 1.0, -1.0, -0.5, -0.333]

again, in this example you can add "if x != 0", but it's not always possible
to tell which
element will fail. for example:

filelist = ["a", "b", "c", "<\\/invalid file name:?*>", "e"]
openfiles = [open(filename) for filename in filelist except IOError:
continue]

the example is hypothetical, but in this case you can't tell *prior to the
exception*
that the operation is invalid. the same goes for generator expressions, of
course.



 -tomer
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.python.org/pipermail/python-dev/attachments/20060424/c3635932/attachment.htm 


More information about the Python-Dev mailing list