Ruby vs Python on Web2.0: Twitter

I always have said that I like Ruby much more than Python, but I really have not tried Python that much.

Here I’m going to port my twitter library from Ruby to Python and write down the things I find out.

Resulting code in Python:

#!/usr/bin/env python
import twitter
c = twitter.Connection("myuser", "mypassword")
c.status.update("mymessage")

Resulting code in Ruby:

#!/usr/bin/env ruby
require 'twitter'
c = Twitter::Connection.new("myuser", "mypassword")
c.status.update("mymessage")

I preffer “Mod::Class” syntax over “mod.Class”. That’s possible due to extensible module syntax in Ruby, where you can have different modules in the same file.

Twitter module in Python:

import rest
class Connection:
	url = "https://twitter.com"
	def __init__(self, username = None, password = None):
		self.conn = rest.Connection(self.url, username, password)
		self.status = Status(self.conn)
class Status:
	def __init__(self, conn):
		self.conn = conn
	def update(self, message):
		res = self.conn.request_post("statuses/update.xml", {"status": message})

Hell, where do I start?

  • __init__: I don’t like to type __whatever__
  • self on every function: I don’t like this either, can’t it just be assumed?
  • self.var: I like Ruby’s @var much better
  • None: I prefer nil, nul, or whatever

Twitter module in Ruby:

require 'rest'
module Twitter
	URL = "https://twitter.com/"
	class Connection
		def initialize(username, password)
			@conn = REST::Connection.new(URL, :username => username, :password => password)
			@status = Status.new(@conn)
		end
		attr_reader :status
	end
	class Status
		def initialize(conn)
			@conn = conn
		end
		def update(message)
			res = @conn.request_post("statuses/update.xml", :status => message)
		end
	end
end
  • I can define the module, or modules
  • I can send hash tables as function arguments without {}’s, just :k => v
  • I can even specify that I want the status variable to be read only very easily with attr_reader

Some other things I don’t like about Python:

In Ruby, since everything is an object, so is an URL, and the URL object can be passed along a lot of functions very easily, and its members can be modified, so I can change que query part of it any time I want, that’s not possible with Python’s urlparse object.

Who thought “?”.join(array) was a good idea? In Ruby you do the same as array.join(“?”).

Arrays and Hashes work in weird ways, for example:

foo = {}
print foo["bar"]

That makes Ptyhon pop, while in Ruby you simply get nil, that makes programming with Hashes so much easier. For example: v = foo[“bar”]; if v….

Also, if you try ” “.join(“foo”, None]) Python would crash, while Ruby’s [“foo”, nil].join(” “) will not.

For web2.0 stuff HTTP Basic Authorization is, well, basic. In Python you either have to implement it yourself, or try urllib2’s API which I don’t understand yet.

Oh, and there is no switch/case statement.

You can check side by side both versions of the code:

So, I still love Ruby🙂

15 thoughts on “Ruby vs Python on Web2.0: Twitter

  1. Pingback: More Ruby vs Python « Webcitizen FelipeC

  2. I love “,”.join(somelist) and somestring.split(delimeter). I’m a Python fan who judges Ruby without having used it. Isn’t Python syntax more consistent and (if you use it a bit more) intuitive? I’ve heard that Ruby syntax is intuitive, but I don’t think so.

  3. How valuable can be a judgment on something if it hasn’t even been tried yet? Not too valuable IMO.

    Anyway, certain things in Python can’t be intuitive even if you use them 1,000 years. For example __self__, what’s up with those __ __? It certainly doesn’t seem to be meant to be used that often.

    And how can ” “.join can be intuitive? The first thing you learn about object oriented programing is that methods are supposed to be actions that an object executes.

    What do you assume by the following?

    dog.chase(cat)

    When you join an array, obviously the thing that you are joining is… you guessed right: an array. Let’s say you want to join a Hash, what are you going to do? [“;”, “=”].join? That doesn’t make any sense to me.

    And what about the following Ruby code:

    array.join(" ").split.join(" ")

    How do you do that in Python?

    " ".join(" ".join(array).split(" "))

    Yeah, very intuitive.

  4. Can you please stop writing Ruby vs. Python articles? As an experienced programmer in both languages watching you nitpick about Python is irritating not only because the majority of your complaints either

    a) have nothing to do with programming in the language, such as using periods instead of :

    or

    b) don’t address Python’s problems, but rather highlight your lack of knowledge in the language.

    For a), whatever. That is your opinion. b) is a totally different kicker though.

    >> I can define the module, or modules

    I’m lost to how you can’t define modules in Python?

    >> I can send hash tables as function arguments without {}’s, just :k => v

    That is because that behavior is unnecessary in Python – it supports true keyword arguments . “func :k => v” vs “func(k=v)”

    >> Arrays and Hashes work in weird ways, for example:

    You mentioned this in another post too. foo.get(“bar”, None). Or you know, if you really don’t want to do that, make an instance of defaultdict and you can return any value you want if the key doesn’t exist by default.

    foo = defaultdict(str)
    foo[“bar”] # “”

    foo = defaultdict(lambda: random())
    foo[“bar”] # who knows?

    >> Also, if you try ” “.join(”foo”, None]) Python would crash, while Ruby’s [”foo”, nil].join(” “) will not.

    Difference in philosophy. That is why dictionaries raise KeyErrors too. Python is explicit, Ruby is more implicit. If your program is “correct” you shouldn’t ever have a None to join anyway; if you do, then Python will notify you of a possible bug.

    >> When you join an array, obviously the thing that you are joining is… you guessed right: an array. Let’s say you want to join a Hash, what are you going to do? [”;”, “=”].join? That doesn’t make any sense to me.

    How would joining a hash make sense? A hash, or dictionary in Python, is an unordered key => value mapping. Considering that a join operation requires an order, joining a hash makes… no sense. But to answer your question, it’d be the same as joining a list. seperator.join()

    >> In Python you either have to implement it yourself, or try urllib2’s API which I don’t understand yet.

    I posted on your other blog post on how to use urllib2. The documentation gives nice, easy examples on the “examples” page. Don’t compare languages if you don’t understand them.

    >> array.join(” “).split.join(” “)

    When would you ever need to do that? Give me a real world example and I will rewrite it just as clean in Python as you could do in Ruby.

  5. For anyone reading my comments on this blog, note that I am not trying to be mean. I just don’t want confused programmers trying to make a decision between Python and Ruby to read this person’s comments and take them as truth. In reality, both languages are almost exactly alike. Python has some pluses over Ruby, Ruby has some pluses over Python.

  6. chris: thanks for your comments. Actually my objective is not to spread FUD about Python. I liked Python very much when I started with it, but as I learned latter; it has a lot of important issues (IMO and a lot of Rubysts).

    I just like Ruby much more. I did these series of posts because I wanted to know if my liking was based on something true. I keep giving Python a chance, and I do research on what’s the best way to do things in it, in fact I usually learn the best way for Ruby the same time I do it for Python, It’s just that I find better answers for Ruby quicker than for Python.

    >> I can define the module, or modules

    I’m lost to how you can’t define modules in Python?

    Can you tell me the module name from that code? You can’t. You can’t define the module inside a piece of code, but the key thing is “or modules”: You can’t define more than one module in the same file in Python. That’s what I meant.

    >> Also, if you try ” “.join(”foo”, None]) Python would crash, while Ruby’s [”foo”, nil].join(” “) will not.

    Difference in philosophy. That is why dictionaries raise KeyErrors too. Python is explicit, Ruby is more implicit. If your program is “correct” you shouldn’t ever have a None to join anyway; if you do, then Python will notify you of a possible bug.


    filter = "where count > 5" if filtered
    order = "order by name" if ordered
    query = ["select * from contacts", filter, order].join(" ")

    I don’t care what names you give to the fact that Python can’t do that, for me it’s better to allow this kind of thing.

    Finally I want to say that I agree that Python has some pluses over Ruby, and the same applies the other way around. Exactly alike? I don’t think so. Perhaps on the superficial level. Ruby was designed in a very different way, and things that very easy in it are completely difficult in Python because the design is different. Take the array,join for example.

    I will keep writing these posts as I still think people are using Python for things that would be much easier in Ruby.

  7. But it seems in your posts that you are advocating Ruby for the wrong reasons! Every Python example you gave was less than optimal – the urllib2 one struck out the most because it almost seems as if you wanted to artificially add lines to an already suboptimal solution by putting every piece of information in a variable when you did not do the same for Ruby.

    I’m sorry, I know you’re entitled to your opinion, I just don’t think it’s fair for people making a decision like this to be presented with information that is clearly flawed. I wouldn’t have made any of these posts if your entries didn’t make Python out to be some sort of inferior beast that can’t do the simplest of tasks, such as retrieving a default value from a dict when the key is nonexistent.

    query = ["select * from contacts"]
    if filtered: query.append("where count > 5")
    if ordered: query.append("order by name")
    # do something with " ".join(query)

    Don’t worry, I wasn’t planning on giving excuses!

  8. I was just trying to show what I saw: Python was not able to return a default value from a dict when they key is non-existent.

    Now people have suggested ways to do what I want, but still: I’m not quite happy because I have to do extra steps either when I fetch a value, or when I create the dict.

    If only Python had Ruby’s capability to redefine classes, I could redefine the Dictionary class (or whatever it’s the name). So I could do that in each and every Python script I write.

    So let me change my complaint: Python doesn’t behave as I would expect by default. In fact that’s the key thing about Ruby: it just works as you would expect. Of course that’s personal taste, but in fact personal taste has a great deal to do with the choice of languages that you use and like, and also how productive you are.

    In my personal case when I want to be explicit I use C, when I just want to write things that work I use Ruby. So why should I like Python’s explicitness?

    Regarding your comment about writing code that is “less than optimal”: please don’t assume that I have ill intentions. I am writing those variables because I expect the url, user and password to be arguments of some functions. If I wasn’t fair that wasn’t my intention.

    Trying to be more fair:

    Ruby:
    require 'net/http'
    def my_open(url, user, password)
    uri = URI.parse(url)
    req = Net::HTTP::Get.new(uri.request_uri)
    req.basic_auth(user, passowrd)
    http = Net::HTTP.new(uri.host, uri.port)
    res = http.request(req)
    end
    my_open("http://foobar.org", "foo", "bar")

    Python:
    import urllib2
    def my_open(url, user, password):
    passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
    passman.add_password(None, fillme, user, password)
    authhandler = urllib2.HTTPBasicAuthHandler(passman)
    opener = urllib2.build_opener(authhandler)
    urllib2.install_opener(opener)
    pagehandle = urllib2.urlopen(url)
    my_open("http://foobar.org", "foo", "bar")

    Notice I left the “fillme” value in the Python example. I’m not so sure what is “The Right Way” to fill that value, but I hope since you have more experience in Python you can help me out with that.

    Even if it where just one line; anyway I would find the Python example more complicated.

  9. I’ve used Ruby, I’ve used Python. I choose Python.

    I don’t like __self__ either.

    I think Ruby does make more sense than Python syntactically (in most cases).

    However, I choose Python for 2 reasons that Ruby can’t touch (IMO): stability & performance🙂

  10. You still insist that Python can”t give a default value for a missing dictionary (hash) key. Dude; mydict.get(key, defaultvalue). This idiom is not exactly uncommon, it’s quite common to see: request.form.get(‘myinput’, 10).

  11. “Besides stability and speed I would add it has a larger enterprise base as well.”

    Based on this, Java is a hands down winner here.

  12. Yeap, I agree with CAG; Java is hands down winner when talking about enterprise base.

    I’m talking about the language. Python gained a larger user base because the language is quite good. Ruby is definitively lagging in terms of stability, speed and user base compared to Python, but since IMO the language is way better I don’t think it’s such a crazy thought that it will eventually equal Python and maybe overcome it in those areas.

    Anyway, I still prefer “mydict[key]” over “mydict.get(key, None)”; it just works as I would expect it to.

  13. The one thing that has kept me with Python, even though I don’t like a lot of the same grievances, is that there’s way more LIBRARIES for it, and it’s been around much longer. Sure, I may hate having to define properties in C#, or I may hate having to write a few extra characters, but looking at the micro features of a language like that really isn’t very productive to the overall picture of shipping a system that does something for business.
    Rubyists also seem to try for succinct, cute code that is tricky to maintain for a developer down the road, as opposed to most Python code that even someone not writing the language can seem to read (assuming the formatting of white space didn’t get hosed in transmission, but luckily the modern IDE’s, like Komodo fix it in a second for you). Having had to support some applications written in Perl, these cute shortcuts, like the one Chad Fowler wrote about enumerable injecting: http://www.chadfowler.com/2007/8/3/enumerable-injecting, are what keep me out of the Ruby community, or more specifically, keep me from hiring work done in Ruby. Just look at his code sample:
    [‘o’, ‘hai’, ‘rly’, ‘srsly’].injecting({}) {|accumulator, value| accumulator[value] = value.size}
    Yeah, that’s pretty.
    At least DHH, admitted at one point about some cute code he wrote, maybe dealing with Rails Routing in the early versions of Rails that he had to redo because it was so unsupportable.
    Anyway, I really think the Rubyists and Python people should really be supporting each other much more because both languages are roughly the same and allow developers to be productive.
    I’m just waiting for the day when all these new Ruby on Rails developers depart their current jobs and the managers are left with a clever codebase that is a nightmare to maintain. And eventually the manager has to have the thing rebuilt…it’s no wonder why Ruby or Python really get much enterprise support. Did the clever programmers learn anything from the Perl days? Oh, wait, all these Ruby on Rails people are young!!!!

  14. Pingback: 100,000 views, and some stats « Felipe Contreras

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s