So I am reading up on python in Mark Lutz's wonderful LEARNING PYTHON book. Mark makes a big deal about how part of the python development philosophy is polymorphism and that functions and code should rely on polymorphism and not do much type checking. However, I do a lot of math type programming and so the idea of polymorphism does not really seem to apply--I don't want to try and run a regression on a string or something. So I was wondering if there is something I am missing here. What are the applications of polymorphism when I am writing functions for math--or is type checking philosophically okay in this case.
The point of polymorphism is that if you write a regression function for, say, Python's built-in numeric types, someone else can use it with NumPy or some other numeric library and not think about it. You don't even have to know about the existence of such libraries to be confident in writing your code correctly. Just use the natural language structures, and leave it to whoever makes the next big numeric library to ensure their numeric types can be operated on normally, their lists and sequences can be iterated over by
for loops, etc.
Breaking polymorphism to defend against sloppy coding or to enforce a certain use of your library doesn't really gain you anything. But it might restrict future users of your code for no good reason.
I was wondering if there is something I am missing here
Not missing anything, but maybe overcomplicating things. You write a function that takes the arguments you want, and document it accordingly. That's it.
I don't want to try and run a regression on a string or something
Neither you nor anyone else should be passing a string into a regression function. Who would do that? Code should not be doing anything by accident — if it is, you're just programming by guesswork, which is doomed to failure in any language.
is type checking philosophically okay in this case.
The answer to this is almost always no.
The general philosophy of Python is that you assume the other people using your code are going to be sensible about it — because if they're not, there's really nothing that will help. No type system, no checks, no built-in language features can defend against someone mashing their face on the keyboard and calling your function with the result.
The overarching reason is this: Python is designed for writing concise, expressive, readable code with a minimum of boilerplate. If you manually add in all the boilerplate yourself, you're defeating the point. So just relax and use the language to express your ideas as neatly as possible :)
You are certainly allowed to do input checking. In some languages, you might check input arguments to make sure they are the appropriate type (i.e., they are of the right class). However, in Python, it is often preferred to check whether the input exposes the necessary capabilities. This is sometimes called Duck Typing, after the maxim that if something walks like a duck and quacks like a duck, it's probably a duck--or at least something that a duck processing function should be able to handle.
To give you a more concrete example, suppose you are writing a function that calculates the mean of a list of numbers. Instead of checking whether the parameter is, in fact, a list, check whether it is iterable (or even better, just try to iterate over it and throw an exception if not). This lets your function work for lists, tuples, sets, files, values from databases, and even as-of-yet-uninvented objects that store collections of numbers. On the other hand, you are certainly allowed, and even encouraged, to do domain-specific checking. If your code receives mathematically nonsensical values (e.g., negative probabilities), it probably should throw an exception or somehow signal an error.
Overall, The Python philosophy seems to be "check as much as you need to, but no more. If the caller does something strange, it's at least partly their problem (like regressing on a string). That said, these are guidelines, not hard and fast rules, so use common sense.