One liners

Michael Torrie torriem at gmail.com
Sat Dec 7 17:56:04 CET 2013


On 12/06/2013 08:27 PM, Roy Smith wrote:
> In article <52a287cb$0$30003$c3e8da3$5496439d at news.astraweb.com>,
>  Steven D'Aprano <steve+comp.lang.python at pearwood.info> wrote:
> 
>> The ternary if is slightly unusual and unfamiliar
> 
> It's only unusual an unfamiliar if you're not used to using it :-)  
> Coming from a C/C++ background, I always found the lack of a ternary 
> expression rather limiting.  There was much rejoicing in these parts 
> when it was added to the language relatively recently.  I use them a lot.
> 
> On the other hand, I found list comprehensions to be mind-bogglingly 
> confusing when I first saw them (read: slightly unusual and unfamiliar).  
> It took me a long time to warm up to the concept.  Now I love them.
> 
>> As for readability, I accept that ternary if is unusual compared to other 
>> languages, but it's still quite readable in small doses. If you start 
>> chaining them:
>>
>> result = a if condition else b if flag else c if predicate else d 
>>
>> you probably shouldn't.
> 
> That I agree with (and it's just as true in C as it is in Python).
> 
> Just for fun, I took a look through the Songza code base.  66 kloc of 
> non-whitespace Python.  I found 192 ternary expressions.  Here's a few 
> of the more bizarre ones (none of which I consider remotely readable):
> 
> --------------------------------------------------
> extracols = sorted(set.union(*(set(t.data.keys()) for t in tracks))) if 
> tracks else []

This is a generator expressions, and ternary ifs are common and often
needed in generator expressions.

> --------------------------------------------------
> c2s = compids2songs(set(targets.keys()) | 
> set.union(*map(set,targets.itervalues())),self.docmap,self.logger) if 
> targets else {}

I suspect the ternary distracted you on this one.  The ternary here is
needed because if targets is None the expression fails.  This part
anyway is a common idiom.

The rest is basically making a set (list of unique items only) of the
combined keys and values from the "targets" dictionary.  Now I'm not
sure why the programmer needs do this, but nevertheless that's what it's
doing.  set.union is used because that can iterate over a list of sets,
which is what the map returns.  I suppose they could have done this, but
it wouldn't be much clearer unless you knew what sets, map and
itervalues do:

if targets:
    c2s = compids2songs(
            set(targets.keys()) |
              set.union(*map(set,targets.itervalues())),
            self.docmap,
            self.logger )
else:
   c2s = {}

In any case the ternary operator isn't really the part you were
complaining about.  Personally if I needed to do this particular
operation a lot (combine keys and values into a set), I'd write a
function that returned the set.  Still can't avoid the ternary, though,
unless you made compids2songs a little smarter (and we don't know what
compids2songs does with an empty set):

def dict_keys_and_values_set (some_dict):
   return set(some_dict.keys()) |
            set.union(*map(set,some_dict.itervalues()))

c2s = compids2songs( dict_keys_and_values_set(targets) ) if targets else {}

or I suppose you could o this:

c2s = {}
if targets: c2s = compids2songs( dict_keys_and_values_set(targets) )

Just a matter of taste.

> --------------------------------------------------
> code = 2 if (pmp3,paac)==(mmp3,maac) else 3 if any(x is None for x in 
> (pmp3,paac,mmp3,maac)) else 4
> --------------------------------------------------

This one probably could stand to be reworked for sure!  A standard if
block would be much clearer.  Definitely an example of a programmer
thinking he was clever... maybe a git bisect could identify the author
and we can shame him.

> Anybody else have some fun ternary abuse examples?

Only the last one seems to be problematic to me.



More information about the Python-list mailing list