PEP 308: some candidate uses cases from live code
Bengt Richter
bokr at oz.net
Sun Feb 9 07:37:48 EST 2003
On Sun, 9 Feb 2003 08:10:17 +0000 (UTC), Martin Maney <maney at pobox.com> wrote:
>Okay, a bleary-eyed survey of about 4000 lines of code from a project
>I've been working on in odd bits of time. Best Available Data, sir,
>but mine own. <wink>
>
>These are the uses of a simple if/else that seemed to me to be at least
>vaguely suitable for the proposed ternary operator; most of the if/else
>occurences rejected were over four lines or had very little in common
>between the if and the else code. I don't believe I omitted any that
>weren't less good candidates than the ones below.
>
>If you think my commentary reveals an imperfectly consistent view of
>the proper use and value of 308's ternary, you may be right. I worked
>on this intermittently over the last few hours, and I haven't gone back
>and "corrected" anything [though I may add a note like this before I
>send this off] just because I was learning how I liked this as I went
>along.
>
>
>Candidate 1 - this is from a simple "one line == one record" CSV parser
>
> else:
> start = i
> j = s.find(',', i)
> if j >= 0:
> i = j
> else:
> i = n
> field = s[start:i]
>
> About all that could be changed here is collapsing the if/else, as i is
> live past the end of the code shown:
>
> else:
> start = i
> j = s.find(',', i)
field = s[start:(j<0?j,n)] # cond ? false_sel, true_sel
> i = j if j >= 0 else n
> field = s[start:i]
>
> I don't find this very convincing, but it has its points. I wrote it so
> as to keep the condition the same, and it's just coincidence that that
> made it come out with the pleasing "j if j >= 0 ..." form. At least I
> find it pleasing. Is that line harder to understand than any one of the
> original lines? Of course. Is it harder to understand than the total
> effect of the four lines it replaces?
>
>
>Candidate 2 - generating bounding dates for a month
>
> first = '%04d-%02d-01' % (year, month)
last = '%04d-%02d-01' % (month<12? (year+1, 1), (year, month+1))
> if (month < 12):
> last = '%04d-%02d-01' % (year, month + 1)
> else:
> last = '%04d-01-01' % (year + 1)
>
> Not really a very promising candidate: there's too much that's different
> between the two values for this to appeal to me. This was the second
> plausible candidate I found after sifting through a lot of Python with
> no simple if/else constructs. Of course a lot of the code I've been
> looking at was written knowing that ternary wasn't a viable option (I
> have used one or another of the kulges a few times, but generally find
> them uglier than four not-quite-emtpy lines of code.)
>
>
>Candidate 3 - calculate "school year" from year & month
>
> if d0.month < 7:
> sy = d0.year - 1
> else:
> sy = d0.year
>
> Becomes, after a little rearrangement:
>
> sy = d0.year - (1 if d0.month < 7 else 0)
sy = d0.year - (d0.month < 7) # this is already 1 or 0
sy = d0.year - (d0.month < 7 ? 0, 1) # this is already 1 or 0
sy = d0.month<7 ? d0.year, d0.year-1 # alternative form
>
> I think this actually expresses the original logic a little more
> clearly: the school year is the day's year unless the day's month is
> January through June; then one must be subtracted to get the calendar
> year during which the school year began.
>
>
>Candidate 4 - preparing to use an optional parameter in generated HTML
>
> if params.has_key('add2url'):
> add2url = '?' + params['add2url']
> else:
> add2url = ''
>
> Could be expressed as
>
> add2url = '?' + params['add2url'] if params.has_key('add2url') else ''
add2url = params.has_key('add2url') ? '', '?'+params['add2url']
>
> This is an example where the short-circuit behavior is important, but
> it's not a terribly convincing example overall since it could easily
> be written as
>
> add2url = ''
> if params.has_key('add2url'):
> add2url = '?' + params['add2url']
>
> This last is almost certainly how I would write this, as there's no
> concrete advantage IMO to the ternary form here. I think I was using
> a common pattern for all setup items in this routine and/or module.
>
> [later: "certainly"? well, maybe, but maybe not]
>
>
>Candidate 5 - another bit from HTML generation
>
> if len(events) > 1:
> sep = ' '
> else:
> sep = '<br>'
>
> Obvious:
>
> sep = ' ' if len(events) > 1 else '<br>'
sep = len(events) > 1 ? '<br>', ' '
>
> In a larger context, this would actually allow me to do away with the
> 'sep' temporary:
>
> if len(events) > 1:
> sep = ' '
> else:
> sep = '<br>'
> ...
> if tail:
> tail = sep + tail
>
> allowing a considerable reduction:
>
> ...
> if tail:
> tail = (' ' if len(events) > 1 else '<br>') + tail
tail = (len(events) > 1 ? '<br>', ' ') + tail
>
> I'm not sure why the calculation of 'sep' was separated from its use
> in the code. This is older code that's been through a couple waves of
> refactorings of the system its part of; possibly 'sep' used to be used
> in more than one location in an earlier version. Perhaps the inlined
> version above should be compared to this rather than the original:
>
> ...
> if tail:
> if len(events) > 1:
> tail = ' ' + tail
> else:
> tail = '<br>' + tail
>
>
>Candidate 6 - again, HTML generation
>
> if colors:
> color = 'bgcolor=%s' % colors[gr % len(colors)]
> else:
> color = ''
>
> Naturally:
>
> color = 'bgcolor=%s' % colors[gr % len(colors)] if colors else ''
color = colors? '', 'bgcolor=%s' % colors[gr % len(colors)]
>
> Hmmm... what precedence does ternary have, again? The previous item
> just seemed to obviously need the parens; this one I'm not so sure
> about.
>
>
>Summary:
>
> I didn't find nearly as many simple if/else uses as I had expected to
> in this project's code. What else have I been working on recently that
> might account for this persistent notion that I ought to have better
> examples than most of these?
>
> The other thing I discovered was that some of the older modules really
> need a good, brisk currying - I came across a few things that made me
> wince. Oh, and Aahz, I know you'll want to hear about this: a couple
> modules with some map'n'filter'n'lambda uses that I'm certain will look
> a lot better as list comprehensions. :-)
>
> Amazing how dated six month old code can look...
>
Regards,
Bengt Richter
More information about the Python-list
mailing list