3 ms·
(Disclaimer: Not meant as flamebait) Not to be a prick, but if you're having "typing" problems with Python, you're using it wrong. Types are almost irrelevant
by zephyrfalcon 16y ago
(Disclaimer: Not meant as flamebait)
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.
- bdr 16y agoNote that you start with "you're doing it wrong" and end with "I personally would much rather". :) You also switch from arguing against type checks overall (could be Haskell) to arguing against Java. 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.
- zephyrfalcon 16y agoHm, I didn't mean to argue against all type checks, just the flavor of static typing as described by the OP (i.e., Java). I don't consider Haskell's type system "rigid"; it's strict as hell, but it's also very expressive. 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.
- Lewisham 16y agoWell of course I'm doing it wrong, I got crashers during execution :) 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!
- zephyrfalcon 16y ago"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 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/ 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.
- Daishiman 16y agoRegardless of the language, when you get to over 50K lines of code, cute tricks need to go out the window.
- ionrock 16y agoHonestly, I program in Python every day and my biggest complaint is that duck typing and dynamic types as a paradigm is not well suited for large projects (like the ones I work on). When the codebase is larger than you can keep in your head, the types become a huge issue. When a bug is at one level of an application you have to figure out what argument was passed in. In a language like Java or C#, it is trivial to follow the trail of objects. In Python, it is cumbersome to say the least. Likewise, if you do adopt duck typing you will eventually find that there is no way around dispatching via types at some point. Again, it is not that huge of a deal, but it ends up being boilerplate-ish code you don't want to write. 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.
- japherwocky 16y agoprotip: the next time you need to quickly find the type of a variable, insert a trace like: import pdb;pdb.set_trace() then run the program, and you'll get an interactive prompt and you can just look at everything in that state. dir( myBuggyVariable)