[Python-ideas] while conditional in list comprehension ??

Oscar Benjamin oscar.j.benjamin at gmail.com
Tue Jan 29 02:34:46 CET 2013


On 29 January 2013 01:12, Ian Cordasco <graffatcolmingov at gmail.com> wrote:
> On Mon, Jan 28, 2013 at 8:02 PM, Oscar Benjamin
> <oscar.j.benjamin at gmail.com> wrote:
>>
>> Although dicts and sets should be considered unordered they may still
>> be constructed from a naturally ordered iterable. There are still
>> cases where it makes sense to define the construction of such an
>> object in terms of an order-dependent rule on the underlying iterator.
>
> They may be, but they may also be constructed from an unordered
> iterable. How so?
> Let `d` be a non-empty dictionary, and `f` a function that defines
> some mutation of it's input such that there doesn't exist x such that
> x = f(x).
>
> e = {k: f(v) for k, v in d.items()}
>
> You're taking an unordered object (a dictionary) and making a new one
> from it. An order dependent rule here would not make sense. Likewise,
> if we were to do:
>
> e = [(k, f(v)) for k, v in d.items()]
>
> We're creating order from an object in which there is none. How could
> the while statement be useful there? An if statement works fine. A
> `while` statement as suggested wouldn't.

I was referring to the case of constructing an object that does not
preserve order by iterating over an object that does. Clearly a while
clause would be a lot less useful if you were iterating over an object
whose order was arbitrary: so don't use it in that case.

A (contrived) example - caching Fibonacci numbers:

# Fibonacci number generator
def fib():
    a = b = 1
    while True:
        yield a
        a, b = b, a+b

# Cache the first N fibonacci numbers
fib_cache = {n: x for n, x in zip(range(N), fib())}
# Alternative
fib_cache = {n: x for n, x in enumerate(fib()) while n < N}

# Cache the Fibonacci numbers less than X
fib_cache = {}
for n, x in enumerate(fib()):
    if x > X:
        break
    fib_cache[n] = x
# Alternative 1
fib_cache = {n: x for n, x in enumerate(takewhile(lambda x: x < X, fib()))}
# Alternative 2
fib_cache = {n: x for n, x in enumerate(fib()) while x < X}


Oscar



More information about the Python-ideas mailing list