[TriLUG] Python syntax question

Aaron Joyner aaron at joyner.ws
Tue Apr 8 15:14:52 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


On Tue, Apr 8, 2014 at 2:29 PM, Brian Henning <bhenning at pineinst.com> wrote:

> Hi Folks,
>
> I know I could try a Python list, but I figured I'd start here, among
> friends.  Anyway, having heard of the heartbleed SSL vulnerability, I
> grabbed the PoC Python script (https://gist.github.com/takeshixx/10107280)
> to try to test my own servers.  Unfortunately, with Python 2.4, I'm getting
> a syntax error on this line:
>
> pdat = ''.join((c if 32 <= ord(c) <= 126 else '.' )for c in lin)
>                    ^
>
> SyntaxError: invalid syntax
>
> Unfortunately I don't know nearly enough about Python to understand the
> nature of this error or how to fix it.  Any help for this Python n00b would
> be greatly appreciated!
>
> Thanks,
> -Brian
>
> --
> This message was sent to: Aaron S. Joyner <aaron at joyner.ws>
> To unsubscribe, send a blank message to trilug-leave at trilug.org from that
> address.
> TriLUG mailing list : http://www.trilug.org/mailman/listinfo/trilug
> Unsubscribe or edit options on the web  :
> http://www.trilug.org/mailman/options/trilug/aaron%40joyner.ws
> Welcome to TriLUG: http://trilug.org/welcome
>


More information about the TriLUG mailing list