Is it ok to type check a boolean argument?

Paul McGuire ptmcg at austin.rr.com
Wed Jan 7 18:48:19 CET 2009


On Jan 7, 11:24 am, Adal Chiriliuc <adal.chiril... at gmail.com> wrote:
> Hello,
>
> Me and my colleagues are having an discussion about the best way to
> code a function (more Pythonic).
>
> Here is the offending function:
>
> def find(field, order):
> ....if not isinstance(order, bool):
> ........raise ValueError("order must be a bool")
> ....order_by = "asc" if order else "desc"
> ....return _find(field + "+" + order_by)
>

<grammar_rant>
First of all, please get used to saying "My colleagues and I..."
instead of "Me and my colleagues". My kids still haven't learned this
(both are in college!), and it annoys me daily.  Sorry for the rant,
you were just the final straw, so I'm taking it out on you.
</grammar_rant>

The offending part of this function is the argument name "order".  If
this is a boolean argument, I would assume that True should be ordered
data, and False would be unordered or randomly ordered data.  The name
"order" really does not clue me in that the two choices are
"ascending" and "descending", nor is it clear what the mapping is to
True and False.

You are right, Python's inference of boolean-ness makes it easy for
coders to guess wrong as to the argument type and still get a program
that emits no exceptions, although possibly doing the opposite of the
intended function.  I would suggest that in your project, you
establish a naming convention for these boolean arguments.  The name
should be descriptive and assertive, so that the value of True is
reasonably intuitive.  Instead of "order", perhaps
"return_ascending_results" with a default value of True.  To further
cue your developers that a boolean argument is desired, you could try
adding "_flag" to all of your boolean arguments, sort of a Reverse
Hungarian Notation.

Or another option altogether would be to define some module level
constants, like this:

ASCENDING_RESULTS = object()
DESCENDING_RESULTS = object()
def find(field, results_order=ASCENDING_RESULTS):
    order_by = { ASCENDING_RESULTS : "asc", DESCENDING_RESULTS: "desc"}
[results_order]
    return _find(field + "+" + order_by)

If anything other than those two constants is passed for the
results_order argument, then a KeyError exception will be raised.  (I
used a similar technique to this in pyparsing's operatorPrecedence
method, in which an argument indicates whether an operator is right-
or left-associative.)

-- Paul




More information about the Python-list mailing list