[Python-Dev] The `for y in [x]` idiom in comprehensions

Steven D'Aprano steve at pearwood.info
Sat Feb 24 00:20:16 EST 2018


On Fri, Feb 23, 2018 at 11:23:04AM -0800, Chris Barker wrote:

> But I still think the original:
> 
> [g(y) for x in range(5) for y in [f(x)]]
> 
> Is always going to be confusing to read. Though I do agree that it's not
> too bad when you unpack it into for loops:
> 
> In [89]: for x in range(5):
>     ...:     for y in [f(x)]:
>     ...:         l.append(g(y))


I think we should distinguish between: 

* actively confusing; and 
* merely not obvious at a glance.

I acknowledge that this idiom is not obvious at a glance, but I don't 
think this comes even close to actively confusing. As you say, once you 
mentally unpack the loops it becomes clear.

Given a potentially expensive DRY violation like:

    [(function(x), function(x)+1) for x in sequence]

there are at least five ways to solve it.

* Perhaps it doesn't need solving; if the DRY violation is trivial 
enough, and the cost low enough, who cares?

* Re-write as a for-loop instead of a comprehension;

* Use a helper function:

    def helper(x)
        tmp = function(x)
        return (tmp, tmp+1)

    [helper(x) for x in sequence]

* Chain the operations:

    [(a, a+1) for a in (function(x) for x in sequence)]

    [(a, a+1) for a in map(function, sequence)]

* Use a second loop to get an assignment:

    [(a, a+1) for x in sequence for a in [function(x)]]


I don't think we need to promote any one of the above as the One True 
idiom. They're all simple, more-or-less obvious or at least 
understandable, and deciding between them should be a matter of personal 
choice and in-house style guides.

 
> BTW, would it be even a tiny bit more efficient to use a tuple in the inner
> loop?
> 
> [g(y) for x in range(5) for y in (f(x),)]

The suggested patch will recognise both `y in (a,)` and `y in [a]` and 
treat them the same as a direct assignment `y=a`.

But if you're writing cross-interpreter code which might run on older 
versions of Python, or implementations which may not have this 
optimization, you might prefer to micro-optimize by using a tuple.


-- 
Steve


More information about the Python-Dev mailing list