user4974662
user4974662

Reputation:

List Comprehension - Python 2.7

I tried to convert the following into a list comprehension, but it's giving me an invalid syntax error. I tried a few solutions such as zipping the combinations, but I can't get it to work.

I'm obviously missing some fundamental understanding of what I can and cannot do with list comprehensions. What is my mistake?

Works

def myfun(x, y, z):
        for c in (x,y,z), (x,z,y), (y,x,z), (y,z,x), (z,x,y), (z,y,x):
            print(c)

Does not work

def myfun(x, y, z):
    [print(c) for c in (x,y,z), (x,z,y), (y,x,z), (y,z,x), (z,x,y), (z,y,x)]

Upvotes: 2

Views: 7944

Answers (3)

Daniele Barresi
Daniele Barresi

Reputation: 623

That's not the point of list comprehensions...

A list comprehension is intended/useful to create a new list of objects, without having to explicitly use a traditional for loop.

From Python documentation on list comprehensions:

List comprehensions provide a concise way to create lists. Common applications are to make new lists where each element is the result of some operations applied to each member of another sequence or iterable, or to create a subsequence of those elements that satisfy a certain condition.

What you're trying, instead, is more like a one-liner to print stuff on screen. You don't really need/care about getting a list out of the list comprehension. BTW: you would only get a list of None objects in this case, because that's what the print function returns. It is not useful and a waste of memory/CPU.

In your case, I would prefer a normal for loop: it would be more readable and explicit (which is always a good thing!).

A couple of notes

If you still really want to use a list comprehension for printing in python 2.7, you will have to first do: from __future__ import print_function. That's necessary because inside a list comprehension you need to use the print function, not the old print statement.

The rest of the list comprehension is ok: you can iterate over a tuple of tuples. That's what (x,y,z), (x,z,y), (y,x,z), (y,z,x), (z,x,y), (z,y,x) is, even without the external parenthesis (which in this form are implicit), because a tuple is an iterable (no need to make a list out of it, as others have suggested).

Also, to be fair: @chepner is right in every comment he made so far.

Upvotes: 2

Daniel Roseman
Daniel Roseman

Reputation: 599490

You have two issues here.

Firstly, you need to wrap all your elements into a list:

[print(c) for c in [(x,y,z), (x,z,y), (y,x,z), (y,z,x), (z,x,y), (z,y,x)]]

Secondly, print is a statement in Python 2, not a function, so it can't be used in a list comprehension as these can only contain expressions.

You can do from __future__ import print_function to change it into a function, as it is in Python 3.

However, this isn't really appropriate in a list comprehension. They are for calling something on every element and returning the result as a list; you shouldn't use them for their side effects.

Upvotes: 6

Eric Dill
Eric Dill

Reputation: 2206

Doing this as a list comprehension is sort of odd since you are creating a list filled with the return value of print which is None. If you really want to do it this way:

def myfun(x, y, z):
    [print(c) for c in [(x,y,z), (x,z,y), (y,x,z), (y,z,x), (z,x,y), (z,y,x)]]

then you need to make the things that you are trying to iterate over an iterable (wrap the (x, y, z), ... in a list)

Also consider using itertools.permutations instead to simplify your code:

import itertools
def myfun(x, y, z):
    [print(x) for x in itertools.permutations([x, y, z])]

I really should stress that it is odd to do this as a list comprehension and you should do this as a for loop to avoid unnecessarily creating that list...

import itertools
def myfun(x, y, z):
    for x in itertools.permutations([x, y, z]):
        print(x)

Upvotes: 3

Related Questions