My experience with Python
During the last 5 months, I have been learning Python. I read a few books about the language and subscribed to various mailing lists, RSS feeds and followed Open-Source projects.
Learning Python was easy and interesting. My experiences with programming languages so far have been mostly with PHP (since 1999), Objective-C, some C, Javascript and Actionscript for Flash. So I was at ease with Python and everything seemed well thought and designed.
Compared to PHP, Python is pretty. Even the syntax is prettier. The obligatory code indentation is in my opinion an excellent idea to make sure your code is readable and respects some coding standards. Compare this with the code you can find in PHP apps libraries where each script has its own way...
Python seems to have been thought from the start. On the other hand, features were added to PHP one after the other in order to "solve the web problem". So compared to Python, PHP looks like an ugly fat blob. It borrowed from C, Perl, Java, C++... In comparison, Python looks more like a nice girl in a pretty dress. But as Rasmus Lerdorf said, PHP was never designed to win a beauty contest.
I started learning Python mostly because I was getting bored with PHP. I write PHP code almost every day, 10 hours a day, so I wanted to try something new. I had to do it on my extra time since PHP is our language of choice at work. I picked Python instead of Ruby because I didn't want to follow the hype around Rails. I was also interested in projects like Python for Series60 from Nokia and pyObjC, a bridge between Python and the Cocoa framework.
As my work consists mainly in writting web application, my first attempts with Python were to see if I could also use it for the web. Well, the answer is not definitive but it's closer to no. Python is not ready for the web. The community is working hard on web frameworks but they go in every directions and none of them is well tested. And none of them is near PHP in terms of ease of use, features and deployement options.
Still, I really wanted so I picked up a simple web framework called Colubrid and tried to find a template engine that would fill my needs. In the past I have been using HTML_Template_Sigma and was after something as simple. Well, without success. There are a lot of template engines in Python but they are either too big and do easy thing the hard way, or they are too simple and don't support the basic stuff you would expect. So I decided to simply port HTML_Template_Sigma to Python.
In a way, I managed. My version supports everything that HTML_Template_Sigma supports. It took me 2,5 days approx. But the experience made me see how a language that tries to win the beauty contest is limited compared to its ugly brother. Here are some of the problems I met:
- No isset(). If you use a variable that is not bound to an object, Python raises an exception, even if it's in a comparison clause. And you have no way prior to this exception to check whether the variable was bound. Some people suggest to catch the exception... This is like the chicken and egg problem.
- Too many array types. PHP has only one type of array even if it can be used in different manners. Whether it is associative or not, the PHP arrays share the same set of funtions. In Python, you get dictionaries, tuples, lists, etc. And they don't have the same API. Arrays are probably the most useful way to store information in my code, with Python I always have to remember which kind of storage I used.
- Values added to dictionaries are not stored in any specific order. Dictionaries are like associative arrays. Except that when you iterate them, the items you carefully added to them are listed in no specific order. This makes them totally useless and even dangerous. And there are no other datatypes provided by default to take care of your data in an ordered way. You have to write your own.
- No easy one liners. I use a ? a : b; quite a bit in my code since it makes it shorter and easier to read (at least for me). You can't do something as simple in Python, you have to use convoluted ways.
There are a lot of other things in Python I felt were missing or wrong compared to PHP. The opposite is also true, but I mostly do web development and in this area PHP is way beyond. I agree that Python is a prettier language but that's not enough. Beauty is a subjective thing and to stay pretty you have to stay slim. I expect a language to provide me with the tools and the syntax to be as productive as possible, eventually with less code.
Actually, a lot of Python users seem to be in love with their language. They even invented a silly word to define and label other people's code : "pythonic" and "not pythonic". It means pretty. For example, interfaces, from Java or PHP5, are not pythonic. I actually got amused by the number of things that were not pythonic.
"Pythonic" is a geek term. In fact, I think Python is a language for geeks. The majority of Python users have no idea about marketing, business, promotion, press, corporate... Commercial terms are dirty. Python programmers like concepts and programming challenges. Python is their playground, their moment of fun, their hobby. There are actually a very little number of Python developers that seem to use the language for their living. Python is often used for prototyping and testing concepts.
I am not a geek and what I am really after is a tool to help me get more productive at work. Unfortunately, Python didn't fill my needs. I was happy to learn it and it showed me some interesting concepts implemented in interesting ways. Now I can read and write Python code that is maybe not "pythonic" but that does the job. Thanks to my initiation, I also discovered Mercurial, a very good RCS written in Python and switched to it from Subversion. I didn't loose my time, I simply had to try.
Now I am learning Ruby and enjoying it so far. It seems to fit the bill, along with Rails as a potential replacement to PHP. There is also an Objective-C/Cocoa bridge called RubyCocoa. Nothing for the Nokia Series 60, but this will force me to use my new Python skills so it's ok. In terms of beauty, I think Ruby won the contest over Python a long time ago. I will report about my experiences with Ruby later on.
Comments
Couldn't agree more with most of what you said, actually I laughed out load when I read how close some of your feelings are to mine. I also learned PHP before learning Python, only to realize how well designed Python is and how bolted together PHP is. Beauty contest definitely goes to Python.
PHP was written for web development and it shows, but it also shows if you try to use it for something else (PHP-Gtk/Desktop app) that it wasn't meant to do. Python definitely has the advantage there.
I think there's no 'easy on liners' for the same reason that the indention is there, makes it readable for those that didn't write it. As easy and quick as 'a ? a : b' is, when scanning over someone else's code where it is used I always have to double take. The same code in an if statement reads more naturally.
Biggest problem for me switching between the two is that I keep dropping ';' in my Python code. :)
I agree with most of this. I am in the same situation except that my main goal in learning Python is to learn something I can use more in my sys admin aspect of my job.
Coming from PHP the array datatype issue is perhaps the largest one. While I've only begun to learn Python it does seem like it will be perfect for what I want, writing scripts to help make managing my dedicated server easier.
What I did find for the dictionary order is that can you get a list of the keys in a dictionary, then sort them, and then loop through the keys to get some sort of order. It's not perfect, but it does work.
If you want a sorted set of keys, you can do:
for key, value in sorted(some_dict.items())
There are several ordered dictionary implementations out there, but none in the standard library, which annoys me as well.
In Python 2.5 you will be able to do "T if COND else F". Won't help you now, but it's on its way. I don't think Guido likes conditional expressions much, but indeed the alternatives can be quite convoluted and buggy, which eventually pushed him over the edge.
isset() isn't something I find I would use, so I'm not sure quite what you are doing. At least the top-level namespace is usually fixed. Attributes can be handled with hasattr(), but even more often I use getattr(obj, 'attr_name', default_value), which won't raise an exception.
In most cases dictionaries and sequences aren't interchangeable, so I guess I don't see the issue there. Tuples are a funny beast. Usually you should use tuples just when you are packing and unpacking, like when you return multiple values from a function. They are intended as very very light objects, not really so much as sequences.
Anyway, just some clarifications. Most things are there in Python, you just might not recognize the patterns when you are looking from them; I think this happens with any language.
I needed isset() to check whether a variable was previously set in a recursive function calling itself multiple times. I use isset() and empty() all over the place in my scripts. I don't think it's a bad habit, it's just something that seems to go along well with a dynamic language.
Interesting - posted a "pro Python" piece a little while back here: http://www.sitepoint.com/blogs/2006/05/13/wxdebug/ [http://www.sitepoint.com/blogs/2006/05/13/wxdebug/]
Personally like Python. The main thing it has is my trust - pretty much without exception, whatever I've touched in Python (be it in the core distro or related libraries) has the "feeling" that someone, who knew what they were doing, took a great deal of care while writing this code. To me that's evidenced by Python projects I've seen that have successfully grown to significant size and still look solid.
I'd agree that Python isn't really "there" web-wise. Technically it is but the problem is you'd need to be position to be able to have complete control over the "whole stack" - server, OS, etc. Think that only really works for small teams with complete control over their destiny. As I see it, it's a problem for "teams" of 1 or teams with too much interference from pointy haired bosses.
On the isset / empty front, think that's kind of a style / mindset thing.
Python discourages playing fast and loose with variables - something like PHP's E_NOTICE is the default. Personally I like that and I think it's part of why Python code bases are able to grow big without too much trouble. Somehow my time spent with Python, I never needed an isset equivalent. Personally I like python for being a little stricter than PHP - "I don't think it's a bad habit, it's just something that seems to go along well with a dynamic language." - agreed - for me it's more about feeling I can trust the code I wrote.
Can only illustrate that by comparison to Perl - probably the most common error message in Perl is "use of uninitialized variable in string concatenation" (try Googling for it). It's usually a sign that something else has gone (often horribly) wrong but the first indication from Perl will be this error. You'll find it everywhere from beginners code to some of the oldest and most mature libraries in CPAN. Aside from the fact it often masks more useful error information, it draws coders into spending endless time putting "defined" (Perl's isset()) in their code and generally not being quite sure what it going on.
On the one-liner front, think Python has quite a few places where it's able to knock more than a few lines off PHP, for example list comprehensions (which I haven't yet fully comprehended) - take this example: http://diveintopython.org/power_of_introspection/filtering_lists.html [http://diveintopython.org/power_of_introspection/filtering_lists.html]
newli = [elem for elem in li if elem != "b"]
newli contains all the elements of li not equal to "b". With PHP's array_filter you can get some of the way there, but you still need a callback.
Anyway - enough already.
the most disturbing point for me when going from php to python, was the array things...
I use arrays all the time in php, they are very flexible and all the use cases have the same API...
in python you have tuples, dictionaries, lists, eyc, and they are & feel different over each one...
Except for the isset() aspect, empty() is the default way you test truth in Python, so you don't hardly need it at all. getattr() with a default (third argument of None) provides the full feel of empty() for attributes.
I'm still rather confused by isset(). Do you mean, you have a recursive function that uses a global variable initialized in the function to share information with later invocations of the function? I would not consider that good style in any language; instead you should probably be passing another argument into the function. Python keyword arguments with defaults tend to be a good way to do this.
Not set vars in PHP are being used as if they would have the value "not set". At least we use them in this way. Or abuse :).
You should probably always assign a value like "not_set" to a variable before using it. And instead of isset(), you could use if ($var == "not_set").
I like the PHP way better because it is shorter. But it is probably just a matter of bad design or bad habits.
"I mostly do web development and in this area PHP is way beyond".
This is true when speaking of PHP architecture and integration with web servers. The language itself does not help much. Simple things:
- every XHTML string with variable interpolation must have all its double quotes escaped. Ugly.
- Most of your code relies on the holy php.ini file.
- No namespace. That would help. For any language.
PHP is much like Perl: most things are implicit (or hidden with ERROR_REPORTING tricks), while Python sells explicitness. Everywhere. This is quite confusing in the first place. But it helps when you spend days reading cowokers code. I have bumped into the same remarks as you when learning Python (after 5 years of intensive Perl), but overall, it has become my language of choice.
Add a comment
The Trackback URL to this comment is:
http://golgote.freeflux.net/blog/plugin=trackback(85).xml

