[Python-ideas] with expression

Andrew Barnert abarnert at yahoo.com
Thu Feb 20 23:01:46 CET 2014


On Feb 20, 2014, at 13:33, Yann Kaiser <kaiser.yann at gmail.com> wrote:

> The first one could be accomplished like:
> 
>    x = [line.split() for line in f] with open(thisfile) as f

Yes, if we have a fully general with expression, we don't need a with clause in comprehensions.

> It would keep f opened while the listcomp is being evaluated. This
> makes me think however of a likely accident:
> 
>    x = (line.split() for line in f) with open('name') as f
>    next(x) # ValueError: I/O operation on closed file.
> 
> This does mirror this mistake though:
> 
>    with open('name') as f:
>        return (line.split() for line in f)
> 
> When what was meant was:
> 
>    with open('name') as f:
>        for line in f:
>            yield line.split()

Or just replace the return with yield from. This is pretty much the paradigm case of when you have to be a generator rather than just return an iterator, which is one of the two major reasons for yield from.

> (Which is, unfortunately, a __del__ in disguise, which is frowned upon.)

No it's not. The file will be closed as soon as the iterator is fully consumed, even if it's not deleted until much later.

Of course it does mean that if you abandon the iterator in the middle you're leaking the generator and therefore the file until deletion. But there are many use cases where that doesn't come up.

> This does raise the question of if we need a "for..in..with" construct
> for purposes other than setting a new "highest keyword density" record
> :-)

As was pointed out to me when I suggested such a construct last year, the only cases where this helps are the two cases where you don't need it. Either it's a statement, so you just use statement with, or you can simulate it perfectly with a two-line function (which I believe is available as more_itertools.with_iter if you don't want to write it yourself). These are the two cases you just covered in this email.

Anyone who wants to argue for this idea should read the previous thread first. (I would provide a link, but searching from my phone is painful.)


More information about the Python-ideas mailing list