How is this evaluated

Steven D'Aprano steve+comp.lang.python at
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)
    return ''.join(collector)


More information about the Python-list mailing list