Towards understanding One Line For loops
<p>After reading <a href="http://stackoverflow.com/questions/12920214/python-for-syntax-block-code-vs-single-line-generator-expressions">this</a> question, I have this PySpark code:</p>

<pre><code>model = KMeansModel(model.Cs[0])
first_split = split_vecs.map(lambda x: x[0])
model.computeCost(first_split)
model = KMeansModel(model.Cs[1])
second_split = split_vecs.map(lambda x: x[1])
model.computeCost(second_split)
</code></pre>

<p>Can I write this into a one-liner for loop? Or these loops are restricted in having <em>only one</em> line in their body?</p>

<p>Note: I am not looking for code-only answers, I want to learn, so please, explain. :)</p>

<hr>

<p>Here is my tragic attempt:</p>

<pre><code>model.computeCost(split) for i in range(2): # &lt;- the semicolon here doesn't feel right..Where to put the other lines?
</code></pre>

<hr>

<p>Edit:</p>

<p>Yes, I know that I can write a regular <a href="/questions/tagged/for-loop" class="post-tag" title="show questions tagged &#39;for-loop&#39;" rel="tag">for-loop</a>, but I would like to understand one-liner for loops. This is for experimenting. You see, when reading others' people code, I see them often, and I am not comfortable with them... :/</p>

<p>What you're calling "one-liner for loops" are actually called"list comprehensions", "dictionary comprehensions", or "<a href="https://docs.python.org/3/tutorial/classes.html#generators" rel="nofollow">generator</a> expressions". They are more limited than for-loops, and work as follows:</p>

<pre><code># List comprehension
result = [expression for name in iterable]
# equivalent to:
result = []
for name in iterable:
    result.append(expression)

# Dictionary comprehension
result = {key_expression: value_expression for name in iterable}
# equivalent to:
result = {}
for name in iterable:
    result[key_expression] = value_expression

# Generator expression
result = (expression for name in iterable)
# equivalent to
def anonymous_generator():
    for name in iterable:
        yield expression
result = anonymous_generator()
</code></pre>

<p>You can nest them, they aren't actually required to be one line. For a (probably-not-useful) example, list comprehensions could be used to get a list of all possible pairs of elements from a list <code>listA</code> and elements from lists in a dict <code>dictB</code> keyed by things from <code>listA</code> (the line break is not required, but helps readability):</p>

<pre><code>pairs = [(a, b) for a in listA
                for b in dictB[a]]
# equivalent to:
pairs = []
for a in listA:
    for b in dictB[a]:
        pairs.append(a, b)
</code></pre>

<p>However, the main limitation of them is that you can't call arbitrary functions - the only places you can put expressions are when saying what iterables you're using and what to output into the result. Side-effects of any functions you call in that will happen, though! For your specific case, you can't do it in any of those simply, because you keep re-assigning model and you can't do that in the middle of a comprehension. It's probably possible to twist things around enough to get the same effect (by writing other functions that do the assignment as a side-effect before returning the correct value), but in this case not really worth it.</p>

python loops for-loop apache-spark pyspark