The Python approach means that when an exception is thrown, it's unclear whose fault it is. Is it a bug in the called function, or in the caller for passing a bad parameter? The larger the program the more of a problem this becomes.
It also means that when you change a function signature, the compiler can't tell you all the call sites you need to fix. You have to find them through testing. This is a large barrier to aggressive refactoring.
Even the Python C API provides facilities for checking that arguments have a specific type and raising TypeError if not, so it can't be that completely counter to the intention of the language: http://docs.python.org/c-api/arg.html (see O!)
> It also means that when you change a function signature, the compiler can't tell you all the call sites you need to fix. You have to find them through testing. This is a large barrier to aggressive refactoring.
This is a problem inherit to every dynamic language. You sacrifice brain-dead refactoring for improvements and tradeoffs elsewhere. Not to mention that modern IDEs and tools like Rope [1] can definitely help.
It also means that when you change a function signature, the compiler can't tell you all the call sites you need to fix. You have to find them through testing. This is a large barrier to aggressive refactoring.
Even the Python C API provides facilities for checking that arguments have a specific type and raising TypeError if not, so it can't be that completely counter to the intention of the language: http://docs.python.org/c-api/arg.html (see O!)