First off, Java isn't a toy language. You've characterized it improperly. Java is a bureaucratic language. You have to cross your t's dot your i's, fill out your requests in triplicate at the FactoryFactoryFactory to get the objectOfYourDesire. Why is this so?
This comes back to how C++ works on projects, especially large projects and midsize projects with a couple mediocre programmers thrown in (because, in commercial software development, you rarely get control of your team). C++ does not work well for large team development unless 1> You have very capable people 2> and you can fire everyone who steps outside the "defined okay subset" of C++ you use on the project. The language is too big, certain parts make it too uncertain, etc, for people to just willy nilly use all the language features. So Java, is basically Sun's "redoing" of C++ where they took its wild west nature, and made a BureauDisney version where you can't do a dozen things that happens in C++ all the time when good programmers go off the reservation or bad programmers enter the equation at all.
C++ has uses, but it's the sulfuric acid of programming languages: you have to have good personnel control and fire those who screw around outside the boundaries of the right style. A programming group with one guy programming like C with classes and another guy programming like it's Ocaml without garbage collection, and you're in for a mighty piece of hell.
So that's where Java came from. That's why it is what it is, and I hope I've highlighted a non-business issue with C++ that comes up from it's overabundance of "understanding breaking powers" which don't mess well with total programmer freedom.
Now lets look at what python was, and what it is now:
Python was originally designed as a substitute for the pascal/BASIC line of programming languages (specifically a language called ABC). It was designed to be very very clear. It still is very very clear. It is still quite terse compared with C++/Java/C, but it's wordier than perl and ruby, but very much clearer for even non-python programmers to decipher much of the time.
Over time, it grew into an Application development and webserver development language. Why?
It has a very easy way to interface to C code. This is important, because C does great module level integration, but once you get at the system level, you start to get issues with namespaces, tracing bugs, etc. So python became an alternative for tying C code together.
It writes very quickly. While you may not understand how to write it quickly yet, usually python/ruby/perl will be quite a bit more productive on a feature basis than Java/C#, and tons more productive than an equivalent C/C++ project. This has to do with the fact it takes very few lines of these languages to "do a job".
For you currently, you're possibly less productive in python right now than you are in C++; I've honestly found this doesn't hold true more than 40-80 hours into learning python development while doing a real project for almost anyone who can handle commercial C++ software development. The C++ people do python faster than they do C++ and it has many fewer issues in the end than C++ they would have wrote. We use weave.inline or something else to speed up the inner loops with some native C, if even required for that application, and all is good, it works just as fast for the user or application, and was completed much faster with much less obtuse bugs.
If you spend those 40-80 hours on the language, you too will likely be a faster developer in python than C++ for many features.
You are not doing C, you are not doing C++, you are not doing Java. Don't pretend you have to do the bueracracy that those languages require. If you write a python program with absolutely no functions, it will run just fine. So if all you need to do is process a small amount of text or open a little server, you can do this in a flat file with just a series of lines of code striaght out of main() in a C program. However with the size and completeness of the python standard library, you'll rarely have to write the rest of the functions.
Secondly, it's important to learn idomatic python today. If you write things like "it's supposed to be" in python today, you get speed on par with C/Java (or only 3-5x slower), and it's really freaky to see an interpreted language do that.
Thirdly, it's important to learn and use the standard language rather than writing code. Python module of the week blog is a great resource to do this: http://www.doughellmann.com/projects/PyMOTW/
Much of python's power comes from a stupidly complete standard library that does much of what you need to do so allows you to write 20 line programs.
Lastly, learn easy ways to fall back on C/C++ in python. This way when you use python for an application it turns out it's too slow for, you can still add a bit of C/C++ to get the speed you need. You can embed C++ inline and have it compiled on the fly with weave, so I suggest you learn that.
http://www.scipy.org/Weave for getting it
http://www.scipy.org/Cookbook/Weave for examples of use
http://www.scipy.org/PerformancePython for examples of how fast this runs vs other things.
This is such an absolutely fantastic way of succinctly describing why I dislike Java so much. Bureaucratic!
Absolutely fantastic post, get this on a blog somewhere. I seriously wish I could upvote you more.
It's like a security blanket for me.
Not to be a prick, but if you're having "typing" problems with Python, you're using it wrong.
Types are almost irrelevant in Python. What matters is whether, in a given situation, the method you're calling is supported and does what is intended. The actual type/class of the receiving object doesn't really matter, ditto for any arguments you pass to the method.
While this may seem highly unsafe and brittle, it has important benefits. You can just hack up some code that "just works" in a few minutes, without having to sacrifice a goat to the compiler first, making sure that all the correct types are specified, subclasses are defined, interfaces are implemented completely, etc. The rigid type systems in other languages often require this and more; making changes to your software becomes a chore. Rapid prototyping this is not.
In Python, when used correctly, you don't have this problem. Write a bit of code, write a test, run it, and decide what to do next. Ideal for testing out ideas. It doesn't work? Throw that shit out and write something else; two minutes later you'll be testing your new code again. Yes, you do need to have unit tests, but the same is (or should really be) true for most languages. Just because something compiles, doesn't mean that it does what you want. (Except maybe in Haskell. :-)
Interestingly, the quickly-written prototype might well be good enough to become the actual production code, with some additions. Just keep you tests up-to-date, for reasonable use cases, and there's no reason why your code shouldn't work in real life. Sure, that function foo(x) that wants to call x.bar() will fail if you call it with an x that doesn't support the bar() method. So don't do that, then! ;-)
Anyway, to summarize, I personally would much rather have Python's flexibility, paired with unit testing, than Java's lack of flexibility paired with compiler checks.
I understand the concept, but sometimes in a medium-size project, you just accidentally send the wrong object back. It happens. But Python won't tell you, and it'll blithely wait for the code to get exercised before dying. I don't remember exactly why I was having this problem, but the bug wasn't shallow, and required a certain confluence of exceptions to occur before it would fire. The sort of thing that would even escape most unit testing.
I would never force static typing on Python or Ruby or upon any language that didn't want it, and when I switched to Python I was very pleased with dynamic typing. However, I find myself much happier with the stronger compiler checks. Writing a medium project in Python now frays my nerves!
I agree that this does indeed happen... I think it's a matter of, the more flexible a language is, the more rope you get to hang yourself with, even unintentionally and unexpectedly.
(Anecdote:) For my work, I have been developing and maintaining a fairly large Python code base... (~70K lines... comparable to about 700K lines of Java <wink>). Another developer changed a module so it would access the database upon importing, which was a no-no (IMHO), so I changed it back, using a class that gets the desired info from the db upon instantiation, and some sort of singleton construct so the same instance would be reused. I also decided to write a test to check that when this module was first imported, there would be no instance of said class yet. To make sure it was a first import, I removed any references to the module from sys.modules, then did an import. This worked great... until I ran the whole test suite using nose [http://code.google.com/p/python-nose/], which has its own ideas about import order and such. This turned out to be surprisingly hard to fix... a non-shallow bug that wouldn't even be possible in less flexible languages.
Tests are effectively the answer, but they are a pain to write and having to document your type information via tests seems a lot more cumbersome from just doing "int my_var".
The party line with Python and dynamic typing is true in many cases, especially when starting a new project. As time goes on though, things get confusing and tests are rarely good enough to offer the same contract static typing offers. To say "you're doing it wrong" is somewhat correct, but no one does it right all the time.
then run the program, and you'll get an interactive prompt and you can just look at everything in that state.
I'd say that strong compiler checks become more helpful as the size of a program increases. You can keep less of a big program in your head, and big programs have more code paths that could potentially need testing.
Either way, both flavors of static typing require development methods that are very different from Python's, though. My original point was that in Python, you shouldn't really have to worry about types, or checking them (in tests or otherwise). You can, but (IMHO) you'd be going against the grain of the language.
Here is a link to doctests. There are godly, and unlike any testing library, in that they aren't a library, they're a comment scanner: http://docs.python.org/library/doctest.html
Smallest amount of rigmarole required to make testing happen I've seen in any language.
Java is almost untyped by comparison. Languages like Ocaml and F# occupy a middle ground.
Take the Java web framework, Play, as an example.
All of Java's features conspire to create a language that's pretty verbose and doesn't do a lot to make things easier for you (aside from simple object orientation). If you like spelling everything out in excruciating detail, that's good. If not, the language doesn't want to twist your arm, but it's certainly not going to do anything to help you.
It'll work from Hong Kong, and probably most places in the world, but if you cross the Chinese border into Shenzhen, you'll get "The connection has been reset". Same with other places in mainland China I've been.
This is the best tip that could be given. In the SICP course in Berkeley CS class, the instructor puts it as
"Don't ask me what the language will do if you do something stupid, the answer will always be either you would get an error or the computer will do something stupid. Don't try to convert java code into LISP, try to think in the language."
"Thanks for responding, that's an interesting perspective" is not a class of comment that deserves downvotes. It's completely appropriate.
(Update: The comment was deleted as I wrote this.)