[TriLUG] Python syntax question

Aaron Joyner aaron at joyner.ws
Tue Apr 8 15:17:48 EDT 2014


Executive summary: That line uses a ternary, which was added in python 2.5.
 Use python 2.7 and it'll "just work".

The longer version:
So... that's a pretty awful chunk of python syntax, if you ask me...  it's
near impossible to read by the standards of good Python style.  It's
essentially a list comprehension (without the braces), also with
an embedded ternary statement.  Ternaries are almost always the wrong
choice in Python. List comprehensions are okay in small measures, but this
one goes way beyond a simple list comprehension where it's easy to intuit
what's going on.

For your edification, let's try to break the whole line down, and see
what's going on.

# The original expression, for reference:
pdat = ''.join((c if 32 <= ord(c) <= 126 else '.' )for c in lin)


# Let's start by defining lin as a list of strings
# which seems to be implied by the code:
lin = ['a', 'b']

# Ultimately, this is trying to set the value for 'pdat',
# let's initially define it as an empty list.
pdat = []

# The core of the list comprehension is:
for c in lin

# Let's pull that out of the tail end of the expression,
# write it as a regular for loop, and build up from there.
# Now we have:
lin = ['a', 'b']
pdat = []
for c in lin:
  # ...

# The ternary conditional is basically this:
if 32 <= ord(c) <= 126:
  # use c
else:
  # use '.'

# since we're not doing it as a list comprehension,
# we can write that out like this:
c = 12
lin = ['a', 'b']
pdat = []
for c in lin:
if 32 <= ord(c) <= 126:
  pdat.append(c)
else:
  pdat.append('.')

# which is functionally equivalent to the original bone-headed expression:
pdat = ''.join((c if 32 <= ord(c) <= 126 else '.' )for c in lin)

Here's a full version of a python script that you can invoke.
Note: it requires python2.7, because it includes the original expression:
----- 8< snip 8<-----
#!/usr/bin/python2.7

def TheHighway(lin):
  return ''.join((c if 32 <= ord(c) <= 126 else '.' )for c in lin)

def MyWay(lin):
  pdat = []
  for c in lin:
    if 32 <= ord(c) <= 126:
      pdat.append(c)
    else:
      pdat.append('.')
  return ''.join(pdat)

lin = ['a', 'b', u'\u2020']
print TheHighway(lin)
print MyWay(lin)
----- 8< snip 8<-----

What is that doing, you might ask?  It's taking a list of integers,
interpreting them as ascii character codes, or '.' if there's no
corresponding ascii character code, and dumping them into a list named
'pdat'.

If you wanted to make just that one line python2.4 compliant, I think you'd
have to break apart the list comprehension much as I have, as I don't think
you can get a single-line list comprehension to incorporate the 'else'
behavior with out a ternary.  Then again, it may be possible, and I might
be willfully ignoring that part of python.  If it *is* possible, it's still
a *terrible* idea.  Abusing list comprehensions inevitably leads to code
which is not easily read by a novice.

Happy coding!
Aaron S. Joyner

PS - Context trimmed because TriLUG list says, "You write too much code in
one email..."


More information about the TriLUG mailing list