7 ms·
I'll offer this qualifier up front: Python is a great language with many interesting features and it has a fantastic spot in the world of data analysis. Having
by lkrubner 10y ago
I'll offer this qualifier up front: Python is a great language with many interesting features and it has a fantastic spot in the world of data analysis. Having said that, I wonder if contract programming is appropriate in Python? I have a similar criticism of contract programming in Ruby and PHP and Perl.
I'm a huge fan of "design by contract" and I strongly advocate for that style when I'm working in any JVM language (Java, Groovy, Clojure, etc). But if you find yourself needing this kind of run-time validation in Python, shouldn't you stop and ask yourself "Is Python the right tool for this job?" (If anyone here remembers reading some old posts of mine, you might recall that last year I was involved in a startup focused on Natural Language Processing, which we first considered using Python for, but then switched to Java.)
My criticism is stronger for Ruby and PHP. I realize that some people compile their Python, which allows optimizations similar to what's available on the JVM. My advice is less absolute when it comes to Python. Whereas with PHP, if you find yourself needing runtime contracts, I would always, always suggest you switch to a different language, I realize the situation is somewhat different with Python. There are more compile and run time options.
The great advantage of the scripting languages is their ease-of-getting-started. PHP and Ruby and Python all recommend themselves to beginners because of the simplicity of the initial setup.
I am willing to believe that Python scales up better than PHP or Ruby. I've seen enough disasters with Symfony and Rails that I'm willing to give Python some credit here (though consider how many complete re-writes Zope undertook).
For my part, as soon as the run time is complicated enough that I feel I need contracts for the runtime environment, I would consider switching to some other language.
- paulddraper 10y ago> I'm a huge fan of "design by contract" and I strongly advocate for that style when I'm working in any JVM language (Java, Groovy, Clojure, etc). Is there an advantage for design-by-contact that Groovy or Clojure have that Python doesn't? Static typing (IMO) goes hand-in-hand with design-by-contract, but Groovy or Closure -- normally -- don't have this.
- p4wnc6 10y agoIt's not so much static typing as functional purity that guarantees design by contract. In a pure language like Haskell, you are forced to go out of your way and do things with glaringly bad code smells to avoid designing by contract. In, say, Scala, F#, or ML, it's easier to subvert by e.g. liberally using mutation or references. In Clojure, it's even easier to avoid, since there's no static type checking, and, arguably in Python it's even easier still. But even in Haskell or Idris, which require extreme lengths taken by the programmer to violate these things, you still can, and you could violate them in a small piece of code that gets wrapped and used all over, spreading the impurity. So at the end of the day, no matter what language you use, these things always boil down to mere conventions that rely on trust of the system implementers. You can trade away some conveniences in order to add extra hoops for convention-violators to jump through -- and you might interpret the existence of the extra hoops as "safety" or some kind of "guarantee". This suggests there should still be use cases when you want conveniences of Python but also want to enforce some degree of hoop-jumping to deter convention-violators. Switching to another language instead, because now Python's lack of intrinsic hoop-jumping guarantees is a problem, comes with it's own costs, and if those costs are significant and related to the major wins that Python was bringing you, then it could easily instead be more effective to just create a few abstractions (and accept performance hits or whatever) to get the hoop-jumping you need in Python. One very common instance where this arises in dynamic typing languages is with subclassing and inheritance hierarchies. You might have a metaclass Foo and you want isinstance(x, Foo) or issubclass(x, Foo) to evaluate True for a wide range of x, some not directly inheriting from x. You can monkeypatch the __instancecheck__ and __subclasshook__ methods on the metaclass to override instance and subclass checking. This is an example where you could get a lot of value out of it. By building that machinery right, later on you can check isinstance and then raise a TypeError, rather than try-excepting an attribute access or something, and you morph a try-except block that might have had a lot of complexity and been a target for code growth when new features get added, and turn it into effectively a much simpler assert statement. You definitely wouldn't want to move away from Python just to get this kind of flexibility out of the box in some other language. But as you ramp up the need for this kind of hoop jumping, say by building some kind of complicated static type checker that uses argument type annotations and fancy metaprogramming with the inspect and typing modules, now you might step back and consider whether, if all that really is needed, you wouldn't just prefer a statically typed language to begin with. And so on...
- pmoriarty 10y agoSwitching to another language is often not very practical, especially if you're working as part of a large team, or need to leverage the ecosystem or community of that language. If you're at a company who've standardized on Python, you can rarely just up and start writing your part of the project in Haskell (even if you know the language, much less if you don't and need to learn it first). And good luck convincing everyone else at your company or even just your team to switch from Python to Haskell (or whatever language you think is the right tool). People get used to their tools, get attached to them, and many won't part with them without a fight. Then there are all the Python libraries that Python programmers have invested a significant amount of time and effort to learn and possibly even love, like numpy, pandas, scipy, etc. If you need the functionality from those libraries, now you not only have to switch languages yourself, convince everyone else on your team/company to use/learn it, but also learn whatever the equivalent libraries in Haskell are (if it has them). Then there's all the Python code at your company that you often need to leverage or interact with. You generally aren't going to rewrite it all in Haskell, and you can't ditch it. So if you're a one-man shop, or are a student with no commitments or demands from anyone else, sure, you can switch languages on a dime (assuming you already know the language you want to switch to). For everyone else, it's rarely that simple, unless those you work with are already fluent and comfortable with the other language and its libraries.
- Bromskloss 10y agoWhat is it that would make contracts suitable in one language but not in another.