More clever (ab)use of
In a comment on the last entry I mumbled yet again how I was annoyed that Python doesn't have an equivalent of C's '? :' conditional expression operator. Then some neurons in the back of my mind woke up and asked 'didn't Guido van Rossum say he was going to add this to Python 2.5?'
In the process of trying to figure out if this
was still happening (it is), I read this message
and found out about a trick (used in the standard library no less) that
gets most of what I want. For '
A ? B : C', we can write:
A and B or C
(Python precedence rules make this equivalent to '
(A and B) or C'.
It works because both
or return the value of the last
expression they evaluated.)
This isn't quite a full emulation of
?:, because it gives you
A is true and
B is something that Python will consider false,
but it is close enough for many uses. Often my code is such that the
A expression isn't true unless
B has a non-empty, non-zero value.
And if your
C is guaranteed to be true, you can always invert the
(This doesn't help the code in the last entry, though, since we
can't guarantee that
blst will be considered true is the caller
supplied it, and our
C default value will be considered false.)
Another day, another useful trick, and it's all because of a comment. (Which makes me very glad I bothered to add comments to DWiki.)
Sidebar: Python 2.5 conditional expressions
From Guido van Rossum's message
, the syntax will be '
B if A else C' (to use my ordering). I'm not
really sure I like this; in general, I don't like out of order syntaxes
because they make me backtrack on expressions when I read them. (I
touched on this before back here.)
According to the Python 2.5 release schedule, Python 2.5 is supposed to come out around 30 September 2006, so we have a while to wait for this.
A trick for handling mutable default arguments
One of the neat things about programming in Python is finding out about clever little idioms that are obvious in retrospect. My latest find is a little trick for handling mutable function arguments.
As I mentioned back when discussing the consequences of
an executable statement, the way I'd been
handling mutable default arguments was something like:
def foo(a, blst = None): if blst is None: blst = 
At two lines, this is just verbose enough to grate lightly but
irritatingly on my nerves. Compressing the
if and the statement
onto one line didn't really help, because Python style is fairly
firmly against that. Then I read an Ian Bicking blog entry, and
the obvious in hindsight shorter version in it jumped out at me:
blst = blst or 
This works because the result of Python's boolean operators is not True
or False, but the last expression evaluated. So '
blst or ' is
if it is considered true and our new anonymous
But there's a subtle (and fortunately rare) gotcha with this, pointed
out by the if it is considered true bit. Namely, if we pass in an
explicit argument that's considered to be false, we wind up with
 instead of it. If you do this a lot and care about it, I
suppose the way around it is:
_none = object() def nonnull(*args): return [a for a in args \ if a is not _none] def foo(a, blst = _none): blst = nonnull(blist, )
This is even safe against silent success if someone accidentally passes
in an explicit
blst argument that turns out to be
because they didn't notice another routine returning
(There is surely a better name for the helper function than
am just bad at naming things.)
Sidebar: another obvious
Today I was writing a case-independent string compare function that needed to have a consistent and stable order if the strings differed only in case. At first I wrote the obvious multi-line function; then I realized I could just write it as:
def ci_cmp(a, b): return cmp(a.lower(), b.lower()) or \ cmp(a, b)
(In my case it wasn't worth memoizing the
.lower() results, or
equivalently doing a Schwartzian transformation; I'm only sorting a list
with a few hundred (short) strings.)