# How is this evaluated

Steven D'Aprano steve+comp.lang.python at pearwood.info
Fri Jul 5 03:41:37 CEST 2013

```On Thu, 04 Jul 2013 10:20:43 -0700, Arturo B wrote:

> I'm making this exercise: (Python 3.3)
>
> Write a function translate() that will translate a text into
> "rövarspråket" (Swedish for "robber's language"). That is, double every
> consonant and place an occurrence of "o" in between. For example,
> translate("this is fun") should return the string "tothohisos isos
> fofunon".
>
> So I tried to solved it, but I couldn't, so I found many answers, but I
> selected this:
>
> def translate(s):
>   consonants = 'bcdfghjklmnpqrstvwxz'
>   return ''.join(l + 'o' + l if l in consonants else l for l in s)

The part inside the join(...) is called a generator expression.

I do not recommend generator expressions (or list comprehensions) for
beginners, because they can be confusing until you understand how they
work. As a beginner, if you have a choice between a one-line piece of
code that makes no sense to you, and a five-line piece of code that you
understand, you should choose the one that you understand.

> So I want to question:
> How is the
>
> if 'h' in consonants else 'h' for 'h' in s
>
> part evaluated? (step by step please :P )

That is the wrong question, because you have split the code in the wrong
places. Your generator expression looks like this:

l + 'o' + l if l in consonants else l for l in s

This is a "generator expression" of the form:

(x for l in s)

where x will be defined below. This part is easy enough to understand:
Python will iterate over the string s, extracting one letter at a time l,
and then evaluate the expression "x" below.

What is the expression "x"? It is this part:

(l + 'o' + l if l in consonants else l)

which forms the "ternary operator" if-clause:

value-if-true if condition-being-tested else value-if-false

If you know C, that's like:

?(condition-being-tested, value-if-true, value-if-false)

The condition being tested is, "l in consonants". The value if true is "l
+ 'o' + l". And the value if false is just l.

So putting this all together, we can convert the generator expression
version to this longer, but more readable, version:

def translate(s):
consonants = 'bcdfghjklmnpqrstvwxz'
collector = []
for l in s:
if l in consonants:
collector.append(l + 'o' + l)
else:
collector.append(l)
return ''.join(collector)

--
Steven

```