[Baypiggies] Type checking - argument for it being bad practice?
Alexandre Conrad
alexandre.conrad at gmail.com
Fri Oct 8 19:08:19 CEST 2010
2010/10/7 Seth Friedman <sfseth at gmail.com>:
> Hi Baypiggies,
> I've encountered, a couple of times now, a sort of categorical "dont do
> typechecking" attitude on various blog posts and I haven't seen rationale to
> back it up. Enough that I'm now curious: what's the deal?
> So I put the question to you all, typechecking: good or bad thing? Or
> pointless philosophical debate?
My general rule of thumb:
- do type checking/conversion as soon as you have input from an
external/untrusted source (e.g., data submitted from a POST request).
- if you need to convert data type, (e.g., a string "123" to an int
123), do it before passing it to your function. Don't have the
function do the data type checking (again, unless data comes from an
untrusted source). Make sure your functions receive the expected data
types as argument. If it crashes or you are getting unexpected
results, it means you are misusing your function (or your function has
a bug).
- keep your function's docstrings up to date. Always start saying what
the function will return (it may return different data types). If your
function expects specific data types, write it in the docstring as "In
the face of ambiguity, refuse the temptation to guess". If the
function accepts different types (say list, tuples, set, dict) because
it will, say, iterate over them, use the word "iterator" or "sequence
of <data type>" for the argument's doc (or anything that makes sense
to you, but preferably, that makes sense to everyone).
And remember: "Special cases aren't special enough to break the rules.
Although practicality beats purity." So sometimes, isinstance() is
useful (but if I use it, I try to rework my code so I don't have to,
plus, I think isinstance is rather slow).
> The best argument I can think of for typechecking=bad is that if underlying
> functions can take more types than obvious, let it try to do the right
> thing, and if it fails, another exception will be likely anyway. I mean
> the TypeError raised with '1'+1 is pretty clear ("cannot concatenate 'str'
> and 'int' objects"), but if it were more complex logic say with home-built
> exceptions expected to highlight the error, I am skeptical.
> I guess a second-best argument I can imagine is about false-negatives ..
> what if I am overly restrictive in my type check and it fails when the (my)
> logic would have succeeded. Well, ok, as with anything gotta be careful
> with typechecking as with the rest of the code. But what if code around my
> function is expecting ints and not floats even if my function can deal with
> both.
> If I'm writing the function and I know I only wrote it to accept single
> numbers and not, for example lists or strings, isn't it cleaner to have at
> the top of my function something like:
> numbersoaccept=(int,float)
> assert(isinstance(inputvar,numberstoaccept))
> ?
> If I don't do this easy check it seems like failures down the road are
> likely to be more convoluted and require more debugging time. And is there
> a better/more pythonic form of typechecking than this assert? If I need to
> extend my function to convert a string '1' to an int or to handle lists, it
> seems better to have an assert that prompts me to remember that there's a
> decision to be made about where to put that logic. It's kind of like
> executable documentation, what's the downside?
> Best
> seth
> _______________________________________________
> Baypiggies mailing list
> Baypiggies at python.org
> To change your subscription options or unsubscribe:
> http://mail.python.org/mailman/listinfo/baypiggies
>
--
Alex | twitter.com/alexconrad
More information about the Baypiggies
mailing list