Python Type Checking

February 07, 2006 at 06:58 PM | categories: python | View Comments

One of Python's strongest points is the fact that it is dynamically typed. That is, it does not force static type checking at compile time.

Take this simple, contrived, example written in Java, which is a statically typed language:

public Car getCar(File file) throws IOException

A lot of information is communicated in this statement. We know that it's public, what it returns (a Car object), that it requires a File object and that if it may raise an IOException exception if it fails. There is a lot to be said for being explicit like this. However, it is limiting as well. What if we wanted to get a Car from a string or from the network instead of from a File object? Well, we'd need to write another function. In addition to that, being that verbose takes a lot more time for me to write. Consider the alternative in python:

def getCar(input):

The second was a lot faster to write and will accept more inputs. For instance the input could be a file, the network, or a string, I just need to write different dispatching code depending on the input type. Most of the time, this means that I can spend less time jumbling with language semantics and get on with my life.

Then there are the other times. What happens when I pass the getCar function a new object that I haven't anticipated? In Java you'd never have this happen because when you compile your code it would realize that the object is not a File object. In Python though, the function takes ANY object and happily starts executing your function/method... that is until it does something to that object that it can't do. In Python you'll find the error at runtime whereas in Java you'll find the problem before it ever occurs, when you compile the program.

So, you can see why alot of Java and C/C++ programmers poo-poo Python. The question is, in the *real world* does this actually ever pose a problem? I really haven't seen an example of it.. Neither has Bruce Eckel. So if it isn't a problem in the real world, but only in hypothetical examples, does it really make sense for a language to force you to define your types Every.. Single.. Time.., thus making you spend more time on contingencies that most likely won't come up? I don't think so.

But... I have to sympathize somewhat with those programmers that DO think about those "hypothetical" examples where it really does matter, because I'm one of those programmers.

Python is all about liberty. Python will let you do things YOUR way. If you want to force people to only use a certain type of object in your functions, you can do it. Yesterday I found a very nice module that does exactly this: The typecheck module. Using this module you can have the best of both worlds. You can leave the menial task of type checking to only when you know you need it. If that's everytime for you, that's fine, the Python syntax isn't any more complex than Java syntax AND it's more flexible.

Here's an example:
>>> from typecheck import accepts
>>> @accepts(int)
... def intFunction(a):
... print a
...
>>> intFunction(1)
1
>>> intFunction("something different")
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "/usr/lib64/python2.4/site-packages/PIL/__init__.py", line 1271, in fake_function

File "/usr/lib64/python2.4/site-packages/PIL/__init__.py", line 1392, in __check_args

typecheck.TypeCheckError: Argument a: for something different, expected <type 'int'>, got <type 'str'>;
>>>

It's still not compile time type checking (you don't explicitly compile Python anyhow), but you do prevent the function from ever running if the function doesn't pass your accepts() filter.

The above example is only the most basic form of runtime type checking. The typecheck module has a lot more examples on their page and also excellent documentation and tutorials. I've also written my own test application using their module.

Type checking could be a powerful tool in finding bugs in programs. The really nice thing about using this as a module, instead of a language requirement, is that I can do my type checking almost as an afterthought. In no way does it impede my programming style or speed.

blog comments powered by Disqus