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:
<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.
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.