Computerworld is undertaking a series of investigations into the most widely-used programming languages. This time we chat with Guido van Rossum, best known as the author of Python, and currently working for Google, CA where he gets to spend at least half his time developing the language.
According go Guido one of the reasons for python was to increase developer productivity. In the old days when most developers used simple editors such as vi, this certainly was the case. E.g. not having to type declarations really saved time, and it still does in small projects.
However, with the introduction of ide’s like Eclipse much typeing in languages like Java is done automatically for the developer, and compilation is done almost momentarily on save, the gain of using python becomes less obvious, and at the same time there is a rather high price in reduced runtime performace to pay compared to e.g. java, especially on modern multicore processors.
Another problem is that not explicityly declare things othen results in introduction of more tests to validate e.g. input to methods if you want to maintain the same robustness of the code as you get in a language where you declare the type of your variables explicitly. These tests not only take time to write, they may also reduce the clarity of the code.
Having explicitly declared variables also makes it easier and faster for new developers to figure out how a large codebase works, as they can be fairly sure what type a variable is without tracking it down to where the value in it was actually created.
One of the good things about python is that whitespace have a syntactic meaning. This means that every programmer will write python code that looks the same and you don’t need to get used to or mix and match between different coding styles. This is very useful if you do team work. But why, why, should developers be allowed to chose between tabs or spaces, and why are they allowed to chose how many (as long as they do it consistently). This makes cut & paste unnecessarily difficult and errorprone.
All in all, I would say python is still very nice in small project of 50.000 lines or so, but becomes less and less of an advantage as projects gets larger, where I personally would prefer Java.
Maybe static and dynamic languages are just approaching the same point in design space from opposite directions?
IDEs and type inference make static typing less of a hassle. On the other hand I can’t see why it shouldn’t be possible to add static analysis to a dynamic language that _tries_ to prove certain things about a piece of code, say a function, and if it succeeds it can do some optimizations. If it fails, however, you could still run the code without optimizations and it could print a warning of some sort.
I mean no offense, but I couldn’t disagree more with your statement regarding productivity, especially when compared with Java.
As far as development goes, Java is a wordy mess of a language, in my opinion, whereas Python is simple, clean, and to the point (for the most part). The reason Java IDEs need all those code-generating features is a direct result of the fact that Java is not a very productive language; syntactically speaking, anyway. So, whether you actually have to write those lines of code, or automagically generate them in the IDE, the fact remains that you have to work with them and debug through them, which is a waste of time.
As far as the statically typed vs. dynamically typed argument goes, I don’t see any more validity in it that I do in the emacs vs. vim argument, or the Linux vs. BSD argument. I have used both types of languages with no noticeable detriment either way.
Finally, There may be some projects out there that Java is a better fit for, but I’d wager that 90% of the Java projects out there could be written in any language with little to no consequence.
I use both Python and Java on a daily basis at work. All I know is that when a situation arises where I need to write some code, and management leaves the choice up to me, I always reach for Python before Java because I can get things done much, much faster.
As a developer, I like Python. I merely tolerate Java.
The point of concise syntax is not to ease the typing, but to ease the reading (one probably reads the code more than he types it in). So you got the argument wrong.
About static vs. dynamic typing, I have mixed feelings. I think it’s useful to have declarations in function parameters and major data structures, but it seems to be too much hassle for local variables and temporary or technical parts of data structures. And even with the declarations, they for the most part miss the interesting stuff, like semantic interpretation (like: If this function returns 0, it means success or not success? What kind of values this function can return?).
Disclaimer: I like Python and don’t like Java, precisely because Java feels _really_ bureaucratic with respect to Python.
Then, perhaps you should not return a 0. In Java 1.4 you could use a constant e.g:
public static final int SUCCESS=0;
or in later java versions you could use Enumerations
enum ReturnState{
success;
failureType1;
failureType2;
}
why not a freaking bool type?
You have some good points.
I have to argue it isn’t just not having to declare types that makes Python good for rapid development. We aren’t talking about saving a few keystrokes and getting rid of a bunch of “int”s or anything.
I learned Java first, then I learned Python. Now when I go back into some Java code I see things like:
stuff = new Vector<Thing>();
for(Object obj: somethingIterable){
    if(obj instanceof Thing){
        stuff.add((Thing)obj);
  }
}
6 lines of code… or in python…
stuff = [obj for obj in somethingIterable if type(obj) == Thing]
1 line of code.
My point here is that if you had to get collections of 3 types of objects out of some big list you would have 18 lines of Java or 3 lines of Python. Sure you could combine all of that onto one line of Java too, but would it be as readable? For something simple like grabbing a type of object out of a list you are making a developer look at 6 lines of code….it is stuff like that all over the place. Less code is easier on the eyes, easier on the brain too. And, with python, its not like perl or some other compact language where you have to stare at a single line for half an hour to see what it does if it has been more than a week since you looked at it. With Python it is very easy to re-visit code and see what it is doing.
Edited 2008-08-05 21:07 UTC
The example I always like to use is opening a file in Java and reading its contents vs. opening a file in Python and reading its contents.
I understand (though I could be wrong) that Java 1.7 will have a new Java.io.File library. Here’s hoping it is a vast improvement over the current one. It certainly couldn’t be worse.
Edited 2008-08-05 21:17 UTC
Note that you have introduced at least two unnecessary lines with ‘{‘ ‘}’. So in fact, it is “just 4”.
Edited 2008-08-05 22:13 UTC
If you follow good practices in Java, you would probably have declared your iterablethings to something like:
List<Thing> iterableThings;
making the code look something like:
stuff=new Vector<Thing>();
for(Thing obj: iterableThings) stuff.add(obj);
Yes, that’s two lines not six, even though I would say it would be more readable as:
stuff=new Vector<Thing>();
for(Thing obj: iterableThings){
stuff.add(obj);
}
As you can see, fewer lines of code does not necessarily mean more readable, regardless what language you use.
If you are a new developer in a large project it is very useful to know what lists are allowed to contain, for that reason it is good practice to avoid lists of plain objects.
Believe me, I have just finished a project where I was to convert a couple of million lines of java 1.4 code (without generics) to java 5. I can assure you that not knowing the allowed contents of lists was one of my major obstacle. To avoid that, I would gladly write one or two lines more. Not to mention that Python would have been out of the question in that project for performance reasons.
Somebody in this thread said that Java have a bit too much bureaucracy, and that may be true, but it is that bureaucracy that saves you when the projects grows.
I called Java “wordy”, but “bureaucracy” fits too. I personally don’t think either is what saves you when your project grows.
I also don’t believe that scalability has to equal stupidly verbose syntax and junk like Java Server Faces.
Let’s be honest. Java could be a lot better than it is.
Edited 2008-08-06 00:20 UTC
Well, if you leave the `if`out of the loop, then in Python the code would be:
stuff = [iterableThings]
People usually confuse Python’s duck typing system to just plain dynamic typing. In my opinion duck typing is an excellent way of doing typing when you put your trust in it.
In the common enterprise style of coding, which I actually don’t have any experience on as I have only worked on small to middle sized projects. I guess people wouldn’t at first look use Python. But with manual type checking (and losing the benefits of duck typing), you can make your code more explicit in regards of types. But this will result in more lines of code than for example using static typing and polymorphism.
I guess in Python, it would be quite easy to create a custom list type (by subclassing from the built-in list), which checks the type of the objects being appended to the list. But that would be a hack.
In Python 3000, we will have annotation support, which wil still allow as to have all the benefits of duck typing style of dynamic typing, but we can also more explicitly “annotate” the types (which are not checked by default), and expand the annotations to be used for type checking.
Here is the PEP (Python Enchancement Proposal) for the function annotations system: http://www.python.org/dev/peps/pep-3107/
Except that in Python, you have no way of knowing that iterableThings actually contains Things, and nothing but Things until runtime, and perhaps not even then.
This a good example, of how you in python sometimes need to compensate the lack of explicit typing by adding more tests for the sake of rubustness of the code.
That is true. You would have to create some additional logic for keeping the types explicitly “clean” if that is necessary. But is it really necessary that often?
For example, with numeric types, is it ever necessary to limit a list of objects to be of type double? With duck typing, everything that looks like a number, works like a number.
Or another common example is file-like objects in Python. If you create functions which for example count all the lines from a file: the input doesn’t need to be a file, as long as it implements the methods that the line counter uses; thus implementing itself as a file-like object. And the rest falls to the exception handling system.
For before-runtime checking, there is for example PyLint.
What I’m arguing: is static typing really so much better, that you wouldn’t want to use the power of dynamic typing?
One thing: remember that reading a program is made more often that writing it!
IDEs may reduce the time needed to write Java or C++, but they don’t do much (except syntax highlighting) to reduce the time spent by the programmer reading those cluttered (Java) or awfully complex language (C++ template).
That said I agree that variable declaration is useful because it provides a needed redundancy and IMHO by default a language (even a scripting language) should expect variable declaration, with an option to do automatic variable declaration which is useful for one-liners (the opposite of how Perl do it in fact).
In dynamically typed languages or statically typed but with type inference, variable declation are not verbose (and don’t need IDE):
“var foo = <expression>;” is enough!
read this
http://steve-yegge.blogspot.com/2007/12/codes-worst-enemy.html
I started by disagreeing, then agreeing in some contexts, now I just plain agree with him. I would still use typed languages for large (< a million loc) enterprise projects, but for everything else I reach for a dynamic language.
Typed languages have too much ceremony to get your point across. What you end up with is mountains of dirt that have nothing to do with your real logic. As stevey says, patterns is only really putting the dirt in fancy boxes, and IDE’s are just tools to shovel the dirt around easier, but neither address the fundamental problem, it is still dirt. A smaller codebase means less surface area for bugs, less maintenance cost, and easier refactoring.
What it comes down to is there are two kinds of people, those who embrace monkey patching, and those who don’t. For those who do, ruby is the way to go, for those who don’t, go python. Both are phenomenal languages, and really quite similar except for that fundamental philosophy (or insanity as the case may be)
No.
I would have asked him…
Why there is no keyword in the language to declare constant, immutable, values (ie. “const FOO_BAR = 666”)?
Other than that… I like the language very much. Thanks Guido!
Edit: spell check.
Edited 2008-08-05 20:06 UTC
Because it isn’t a statically typed language; maybe?
Why should that stop you from being able to declare constants?
It doesn’t. It is simply the reason there isn’t a keyword to define a constant.
Exactly. Having a keyword to declare something as immutable would be very beneficial.
I like how help(sys) says…
__stdout__ — the original stdout; don’t touch!
Look what I can do….
>>> import math
>>> math.pi
3.1415926535897931
>>> math.pi = ‘haha’
>>> math.pi
‘haha’
It would be nice to have things enforced at the language level especially when it seems like everything in Python has global scope.
read up on domain specific languages, or inversion of control/dependancy injection patterns and you will see the value of throwing stuff like const or abstract or static out the window.
It’s actually quite simple. Assignment in Python doesn’t change value of target object, it will just change name to point to some other object, and the original object may or may not get destroyed.
It would be quite easy to create an object that would behave like constant.
A couple of other comments…
Global variables are a bad idea to use. I can see wanting a constant though.
Python does have immutable data types, like a tuple. There is nothing preventing you from having a tuple with just one item in it. You could also put all your constant variables in one tuple and access them that way.
Also, you could do something like this if you wanted a constant:
class Test(object):
def __init__(self):
self.__name = ‘Tboo Ted’
Then, as long as you don’t provide the accessor to change __name, it will always be Tboo Ted because you can’t access it to change it outside of the class (at least this is the functionality in Python 2.5. I believe in earlier versions of Python the double underline was a convention that was not enforced).
EDIT: OSNews’s comment system collapsed the tabs in the above code. The __init__() method should be tabbed in once and the __name variable should be tabbed in twice.
Edited 2008-08-05 20:47 UTC
mypi = (3.141)
# great, I can’t change it now…or can I?
mypi = (666)
# Okay, so I didn’t change the original object, but I was able to redefine it.
Two problems…
1) You haven’t declared a tuple. A tuple in not declared by the parenthesis, but rather by the trailing comma, which you left off.
These are tuples:
pi = (3.141,)
pi = 3.141,
This is not:
pi = (3.141)
2) You are reassigning a completely different tuple to pi when you do something like this:
pi = (3.141,)
pi = (666,)
The tuple is not immutable, its values are. So if you do:
pi = (3.141,)
pi[0] = 666
Then you will get an error.
You have to take some responsibility as the programmer to use the language the way it was meant to be used and to understand its quirks.
If a developer really can’t refrain from changing variable values that they don’t want to change, then go ahead and use the constant code I provided in a previous post.
Edited 2008-08-05 21:33 UTC
@BiPolar
You can create your own constant keyword, so to speak, by doing the following.
1) Create a file called “const.py” and enter the following code into it:
#!/usr/bin/env python
class _const:
__class ConstError(TypeError):
____pass
__def __setattr__(self, name, value):
____if self.__dict__.has_key(name):
______raise self.ConstError, “%s is a constant” % name
____self.__dict__[name]=value
import sys
sys.modules[__name__]=_const()
Note: Replace the underscores at the beginning of each statement with tabs. I just put them here due to the OSNews comment system’s penchant for removing tabs.
2) Save const.py in your site-packages directory, or add the directory containing this file to your Python path.
3) Type “python” at the command prompt to go into the Python interpreter.
4) Type the following:
import const
const.tax = .0625
const.tax = .0715
The second statement (const.tax = .0715) will cause an exception to be thrown and will not allow the constant to be re-bound to a different value.
Edited 2008-08-05 21:12 UTC
Thank you Clinton.
I was aware there where ways of “simulating” constants as I wanted them. That’s why my question said “why”. I would really like to see what’s the rationale behind leaving out such (for me) fundamental programming concept.
I happen to have to work with a huge code base in an scripting language that I won’t mention it out of shame (cough, from Redmond, cough).
Like it or not, we have to deal with TONS of constant values in our code. I would rather use Python (already introduced it), but then again… not having “const” means I’ll have to pay extra care so nobody in our teams commits a silly “math.PI = 3.01” and screws everyone’s results.
Thanks again for the tip.
Note that constants aren’t that easy to specify:
1)do you allow a const pointer to a mutable object or not?
2)mutable reference to const?
3)may an object change its attributes even though it is a constant?
Memoization don’t change really the object, yet it modifies its attributes..
The classical example for this is the ‘complex’ class: say you initialise a complex with its cartesian coordinates, with a flag saying that polar coordinates attributes are undefined (because you may not always need them) and the first operation which needs to compute the polar coordinates store them in the object.
In a way, this object is a constant, yet its members are modified..
So const is really a tricky subject, and C++ didn’t help!
Actually the only thing I see wrong with Python is that it still ships with the Tkinter GUI toolkit as its standard for GUIs. This toolkit is obsolete in two ways, the first being its Motif look under Linux and BSD based platforms using x11 and the second being its virtually Windows 3.x widget choice and functionality. Yet another problem with Tkinter is that it requires the running of TWO programming language interpreters (both TK and Python) for GUI programs making it slower than managed languages having their own GUI toolkits like Java/Swing and C#/Forms.
What Python needs in the GUI area is either a toolkit coded in Python itself with modern widget design, choice and functionality so that only one interpreter/managed environment is needed to run them ala Java/Swing and C#/Forms or shipping with one of the popular C++ toolkits used with Python probably wxWidgets/wxPython rather than the obsolete and second interpreter dependent Tkinter.
I completely agree. I personally like PyQt better than wxPython, but either one would be a huge improvement over Tk.
I think it would have to be a native python toolkit or wxPython because I believe that the python developers want Python available to Proprietary and F/OSS software on an equal basis. The high prices for QT licenses would proclude this if pyQT were used as the shipping GUI library for Python. however wxWidgets does have a pretty complete and modern widget set. (Only drag and drop and tool tips are missing from the wxUniversal x11 based version of wxwidgets which is probably the one that should be used with *nix based python distributions to prevent GTK dependency conflicts between Linux and BSD distributions. These conflicts are also present with QT
with people running version 2, 3 and 4 software these days depending on the power of their computers.
Edited 2008-08-06 06:29 UTC
Good point.
Define “ships with”. Tk is optional and you don’t have to install it.
Also, how many apps today actually uses Tk? If you don’t like it just use PyGTK, PyQT, wxPython or whatever and move on.
wxWindow is horribly slow on OS X and Linux.
pyQT has it licensing issue.
pyGTK is not cross platform. In OS X you need X11 and it’s painfully ugly. In windows it look better yet, but still awkward.
Sure these are good toolkit. But there’s no clear winner.
There was an ANYGUI toolkit (AFAIR) but I think it lost momentum.
Frankly it is a shame that there isn’t a standard cross platform GUI toolkit for Python. A great opportunity missed in my book.
Jython and Swing have tempted me in the past but never enough to do anything about it!
A
I am a hobby-programer. One of the most fantastic things in Python for me is interactive console: I cannot even imagine, how many hundreds of hours I would waste, if I had to compile my programs just to see if the new module/function I learn works the way I suppose it should — usually it doesn’t .
Console integrated with IDE helps in debugging: you can ask IDE to load the current function into console and then run it with controlling parameters; helps to learn: just take your crazy idea of the kind “will it work or blow my computer up?” and check, be it one loop with xml iterator built with 2 lines of code and working on a file opened with the third one or a simple sql client of 4 lines. And you instantly see the results: if you don’t like them, just press “up”, modify the bad line, hit “enter” and see the new results again.
http://www.dreamsongs.com/Files/PatternsOfSoftware.pdf
A really good read for the Java v. Python flame war, or any other…unless you’re on the Java side of the argument .