== 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 _def_ being an executable statement DefAsStatementConsequence]], 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 http://blog.ianbicking.org/reducing-boilerplate-code-in-init.html]], 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 _blst_ if it is considered true and our new anonymous _[]_ otherwise. 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 _blst_ being _[]_ 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][0] > > 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 _None_ (perhaps because they didn't notice another routine returning _None_). (There is surely a better name for the helper function than _nonnull_; I am just bad at naming things.) Appropriately, the [[Ian Bicking blog entry]] I found this in is called [[Reducing boilerplate code in __init__ http://blog.ianbicking.org/reducing-boilerplate-code-in-init.html]], although he is talking about something much higher level than this. === Sidebar: another obvious _or_ trick 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.)