Search code examples
pythontypesexceptionduck-typing

Python: Duck-typing vs. Exception Handling


A question on idomatic Python. Suppose I have a function:

def a_function(list_of_things):
    for item in list_of_things:
        process_item(item)

Now suppose it's difficult for me to be sure that the input argument is a list. Even now, I can hear the sweet pythonista chorus imploring me: "Use duck-typing and exceptions!"

def a_function(list_of_things):
    try:
        for item in list_of_things:
            process_item(item)
    except:
        pass # . . . or something

And this is great, unless I pass in a map, or a string, or anything else that is iterable in a fashion that I find to be "wrong" for this particular application.

I don't write a ton of Python, but I manage to run into this and related situations often enough for it to annoy me regularly. More generally, I want to use duck typing and exceptions, as seems to be the convention in Python, but getting an incorrect input type that passes my exception is possible in a lot of cases; so many that exceptions seem like the wrong answer as often as not (or at least quite often).

Even if exceptions do seem like the right answer, I'm still afraid when I use them, because what if I just haven't thought of the corner case where a bad type will pass, leaving my code, for lack of a better term, "ducked".

So I end up resorting to things like type and isinstance. From my reading, it seems like explicit type checking is considered evil in Python, but what else to do? Note that I almost never compose class hierarchies in my Python, so I don't have issues with subclasses and type checks, but others might.

I've thought of four possible answers, all of which seem equally likely to me:

  1. You should be using exceptions, but you're doing it wrong. Do it like this . . .
  2. You should be using exceptions. If bad types pass your checks, it's indicative of some problem in your design (what problem?)
  3. You're doing the right thing. Explicit type-checking is preferable in these situations.
  4. You don't know about <python thing for this situation>? Do some research!

Is is one of these, or something else?

Note - I found a lot of questions on SO that beat around the bush about this, but I'm looking for people to speak to this specific "genre" of problem if they can.


Solution

  • A best practice is, to be type agnostic. The for-loop raises an exception for any non-iterable type. The documentation should state clearly, that an iterable type is required. Functions using your function should have unit or integration tests, so that unexpected behavior is discovered.