How is this evaluated

Jussi Piitulainen jpiitula at
Thu Jul 4 20:22:21 CEST 2013

Arturo B writes:

> 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)
> print(translate('hello code solver'))
> 'hohelollolo cocodode sosololvoveror'
> ______________________________________________________________
> 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's nonsense in two different ways. The actual expression in the
solution you found makes sense. It's a generator expression of this

   expression for l in s

And the expression in it is this conditional expression:

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

The value of this conditional expression is (l + 'o' + l) if l is in
consontants, for example 'tot' if l == 't'; else it is just l, for
example 'i' if l == 'i'.

Fully parenthesised the whole expression is this:

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

The value of this expression yields the values like 'tot' and 'hoh'
and 'i' for each letter l in s in turn.

> ''.join('h' + 'o' + 'h' if 'h' in consonants else 'h' for 'h' in s)

This is still nonsense. To make sense, replace each 'h' with h.

Then ''.join can eat up the values of a generator expression to
produce the string like 'tothohi...'.

You can experiment with the components of this complicated expression:

   >>> list(x for x in 'plaintext')

   >>> 'x' if True else 'y'
   >>> 'x' if False else 'y'

   >>> list((x + 'o' if x not in 'aeiouy' else x) for x in 'plaintext')

   >>> for x in 'plaintext': print(x + 'o' if x not in 'aeiouy' else x)

I suppose you understand this:

   >>> ''.join(('tot', 'hoh', 'i', 'sos'))

Note that a similar-looking expression in brackets [] is a list
comprehension; in braces {} it is a set comprehension, or a dictionary
comprehension if the value expression is a key : value pair, with the
colon. And this is not all: there's nesting and filtering, too. The
different uses of the keywords 'for', 'in', 'if', 'else' are a bit
subtle but one sort of learns to see the whole expression.

I tend to use line breaks and parentheses in such expressions:

   ''.join(c + 'o' + c if c in consonants else c
           for c in message)

   ''.join((c + 'o' + c
            if c in consonants
            else c)
           for c in message)

More information about the Python-list mailing list