8

I am experiencing a bit of confusion with how to place a for loop at the end of a line in python, for instance

for i in x:
    print i

produces the expected result but if I run

print i for i in x

I get a syntax error. Could someone explain a little more about how one goes about putting your for loops at the end of a line like this.

7
  • 1
    As several answers have pointed out, if you tell us what you're trying to do there may be a better way to help. If you're honestly trying to print all the items from an iterable, for i in x: print i is the clearest and most explicit way to do that. Commented Mar 12, 2014 at 22:46
  • In Python 3, print(i for i in x), since print is now a function. Commented Mar 12, 2014 at 23:13
  • 1
    @Will that will give you some lovely output like <generator object <genexpr> at 0x7f2d794b5500> Commented Mar 12, 2014 at 23:18
  • @wim, oops, make it into a list: print(list(i for i in x)). Commented Mar 13, 2014 at 1:33
  • no, that is equivalent to printing list(x) or [i for i in x] which is something else. Commented Mar 13, 2014 at 1:38

5 Answers 5

8

In earlier versions of Python, the idea of list comprehensions was introduced to neaten up these two patterns of code:

# Go through each item in a list and run a test on them
# build a new list containing only items that pass the test

results = []
for item in somelist:
    if sometest(item):
        results.add(item)

and

# build a new list by changing every item in a list in the
# same way

results = []
for item in somelist:
    results.add(2 * item)

by adding a new syntax that includes doing all three things in one - changing the items and/or testing them to only include some in the result, and creating the list of the results:

results = [2 * item for item in somelist if sometest(item)]
# results is a list

This feature uses the [] syntax that indicates "list" in Python, and it builds a list right away in memory.

Sometimes you don't want or need the entire list built in memory right away, so later versions of Python introduced generator expressions - the same idea, but they save memory by quickly returning a generator which you can iterate over as if it was a list, and it builds the list as and when you use it.

But they can't have the same syntax and be a direct swap out because they behave slightly differently, so they use () instead of [], e.g.:

somelist = [1,2,3,4,5]
results = (2 * item for item in somelist if sometest(item))
# results is a generator

If you try and call a function with this, you get two layers of parentheses:

function((2 * item for item in somelist)) 

Which looks silly, so you can leave one out:

function(2 * item for item in somelist)

Which appears to be a standalone backwards for loop on its own, but it actually isn't.

So with parentheses you can write this:

>>> print (item for item in [1,2,3])
<generator object <genexpr> at 0x7fe31b8663c0>

Which is the closest thing to what you wrote that is valid syntax in Python 2.x, but it doesn't do what you expect, and ^^ is what it does and why.

Or this:

>>> print [item for item in [1,2,3]]
[1,2,3]

Which generates a list and prints the list, the other close thing to what you wrote, but still not what you expected.

-- (there really isn't much point in me posting now a bunch other answers have appeared while I was writing this, but eh).

Sign up to request clarification or add additional context in comments.

2 Comments

Love your answer! Much more complete than mine. Throw in my note about the starred genexp printing (more or less) as expected and I'll toss mine
@adsmith thanks :). I'm not Python 3 enough to know about the starred genexp printing and be comfortable with what it's doing, and I don't want to just copy your answer into mine. Besides you have comments too. I'll upvote you
1

expression for i in x

doesn't mean anything by itself in Python. You can have

(expression for i in x)

[expression for i in x]

But you can't do

[print i for i in x]

because print isn't an expression, it's a statement.

Comments

1

First of all:

  1. this is considered bad style—you're essentially just abusing the list comprehension syntax to get what's effectively a different notation for imperative for loops.
  2. this only works in Python 3 where print is a function by default, or when you do from __future__ import print_function in Python 2.x

However, if you insist on putting the for ... part after the print i part, you can do:

[print(i) for i in x]

(but I'm writing that example for purely "academic" purposes)

P.S. if you let us know what you want to do, we might be able to provide a suitable overall solution, but if you're just asking for the sake of it, then that's it.

1 Comment

I was about to downvote for using side-effects, then read the rest of your post and noticed that you strongly advised not to do this for that exact reason. +1
1

You can't. You've probably seen a generator expression, which takes the form x for x in iter. a for loop is slightly different, though you can definitely see for x in iter inside the genexp.

In Python3, you can do:

print(*(i for i in x))

And as @wim points out in the comments, you can make it more "for loopy" by doing

print(*(i for i in x), sep='\n')

You can of course do arbitrary changes since this is a genexp, so e.g. i**2 for i in x will give you the square of each item in x, i for i in x if i%2 will give all odd numbers in x, etc.

This will create a generator of each item in x, then pass each one in turn (using the * assignment the same way *args is built and etc) as separate arguments to print

3 Comments

Is that any different from print(*x)?
@wim not if you're using it as written, but since it's a genexp you can do print(*(i for i in x if condition)) or etc.
Ah yes. You might want to add sep='\n' to make it more equivalent to the for loop, but +1 anyway.
1

The only thing I can think of that is equivalent in python 2.x would be this:

print '\n'.join(str(i) for i in x)

But don't do that. The for loop as you had it is much clearer.

If you are just fooling around in interactive interpreter and want to one-liner it for some reason, this will work:

for i in x: print i

But it's violating pep8 so I wouldn't write a line like that into a script.

1 Comment

For other readers, I went looking to see which part of PEP 8 (the Python code style guide) it violates, and the guide is here: legacy.python.org/dev/peps/pep-0008/#other-recommendations and in section Whitespace: Other Recommendations it says "Compound statements (multiple statements on the same line) are generally discouraged".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.