Python vs. Ruby: Which Is Better For Every Programmer and Why?

Nov 6, 2018 | 4800 Views

So the question is Python Vs Ruby. Before we actually make a choice on this, let's just say that there is a lot of talk about this and to an extent you could say that the debate has been laid to rest. However, here in India, apart from the small fraction of people involved in competitive coding or open source contributions, this is still a burning question. Which of these two languages, which is rapidly increasing in popularity, should one learn to get a job?

India is an interesting programming ecosystem. Most software skill adoption is directly related to its usefulness in landing a job. I have personally come across students who've told me that they'd been advised to learn python or ruby over the other because it will help them get a job. They aren't wrong, as they're speaking from what they know.

But let's do some research. To understand why a job would require you to learn one of these languages, I think it is important to understand the differences between the two languages.

How are the two different from each other? 

The two programming languages have philosophical differences. While Python believes in having only one way to do something, Ruby is built around the philosophy of having many ways of doing the same thing.

Python is modeled after the Fortran line; there is a clear distinction between expressions and statements, and between code and data. This makes it faster, and better suited to top-down programming. It is a lot easier to learn and to understand when reading it.

Ruby, on the other hand, is modeled after Lisp; there is no difference between expressions and statements, and code and data. The most striking commonality is how similar Ruby's blocks are to Lisp's closures. This makes it easier to do metaprogramming to solve problems, and so it is more suited to bottom-up programming.

The Zen of Python:
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one- and preferably only one -obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than right now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea - let's do more of those!

Ruby
Self-introduction:
A dynamic, open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write.

Ruby is modeled after Lisp; there is no difference between expressions and statements, and code and data. The most striking commonality is how similar Ruby's blocks are to Lisp's closures. This makes it easier to do metaprogramming to solve problems, and so it is more suited to bottom-up programming. The thing that Ruby has lost, however, is Lisp's main "love it or hate it" feature: its syntax. Rubyists prefer their language's syntactic quirks, and believe that "there is more than one way to do it". Ruby is more interested in programmers than programs.

Let's see the main differences
Ruby has a class reference in the class body
In Ruby, you have a reference to the class (self) already in the class body. In Python, you don't have a reference to the class until after the class construction is finished.
Ruby code example:

class MyBeautifulClass
puts self
end
There is no way to print out the class name or in other ways access the class from the class definition body in Python (outside method definitions).
All classes are mutable in Ruby
This lets you develop extensions to core classes. Here's an example:

class String
def starts_with?(other)
self.index(other) == 0
end
end
Now all strings have this method.
Python (imagine there were no starts with the method):

def starts_with(s, prefix):
return s[:len(prefix)] == prefix
You could use it on any sequence (not just strings). In order to use it you should import it explicitly e.g. "from some_module import starts_with"

Ruby has Perl-like scripting features
Ruby has first class regexps, $-variables, the awk/perl line by line input loop and other features that make it more suited to writing small shell scripts that munge text files or act as glue code for other programs, e.g.:

$&	#The complete String that matched the last Regexp, or nil if the match failed.
$` #The string preceding the last Regexp match, or nil if the match failed.
$' #The string following the last Regexp match, or nil if the match failed.
$+ #The highest group matched by the last successful Regexp match.
$1, $2, ... #The match for the first, second, etc. parenthesized groups in the last regular expression.
$~ #The MatchData of the last Regexp match in the current scope.
Ruby has first-class continuations
Thanks to the callcc statement. In Python, you can create continuations by various techniques, but there is no support built into the language.


def level3(cont)
cont.call("RETURN THIS")
end

def level2(cont)
level3(cont)
return "NEVER RETURNED"
end

def top_level_function
callcc { |cc|
level2(cc)
}
end

answer = top_level_function
puts answer # => "RETURN THIS"
The block passed into the "callcc" method has a parameter which is also a block. This parameter block is a bit of code that returns control back to the original calling code, immediately after the "callcc" method was called, along with restoring the entire context from when the original call was made.

Ruby has blocks
My favorite part. I even wrote a bit on the topic in my "old" tech blog: Why Ruby? Part Two - Blocks and Closures

With the "do" statement you can create a multi-line anonymous function in Ruby, which will be passed in as an argument into the method in front of do, and called from there. In Python, you would instead do this either by passing a method or with generators.

Ruby:

amethod do |here|
many=lines+of+code
goes(here)
end
Python v1:

with amethod() as here: # amethod() is a context manager
many=lines+of+code
goes(here)
Python v2:

for here in amethod(): # amethod() is an iterable
many=lines+of+code
goes(here)
Python v3:

def function(here):
many=lines+of+code
goes(here)

amethod(function) # `function` is a callback
Ruby supports functional style programming a bit more (easily)
Ruby example:

users.map(&:name).reject(&:empty?).join("\n")
Python example (feels unnatural and harder to read to me):

user_list = (u.name() for u in users)
"\n".join(filter(len, user_list))
Python has a nice flexible namespace handling
In Ruby, when you import a file with require, all the things defined in that file will end up in your global namespace. This causes namespace pollution. The solution to that is Ruby modules. But if you create a namespace with a module, then you have to use that namespace to access the contained classes.

In Python, the file is a module, and you can import its contained names with from the module import *, thereby polluting the namespace if you want. But you can also import just selected names with from the module import name, another or you can simply import the module and then access the names with the module.aname. If you want more levels in your namespace you can have packages, which are directories with modules and an init.py file.

Python has docstrings (man, do I miss them in Ruby‚?¶)
Docstrings are strings that are attached to modules, functions, and methods and can be introspected at runtime. This helps for creating such things as the help command and automatic documentation.

def complex(real=0.0, imag=0.0):
"""Form a complex number.

Keyword arguments:
real -- the real part (default 0.0)
imag -- the imaginary part (default 0.0)

"""
if imag == 0.0 and real == 0.0: return complex_zero
...
Python has multiple inheritances
Ruby does not ("on purpose" - it uses mixins). It does reuse the module concept as a type of abstract classes.

Python has list and dict comprehensions
Python:

res1 = [x*x for x in range(1, 10)]

res2 = (x*x for x in range(10))

res3 = {x:str(y*y) for x,y in {1:2, 3:4}.items()}
Ruby:

res1 = (0..9).map { |x| x * x }

p = proc { |x| x * x }
res2 = (0..9).map(&p)

res3 = Hash[{1=>2, 3=>4}.map{|x,y| [x,(y*y).to_s]}]
I think the Python version is much cleaner and nicer.

Python has decorators
I love them. Similar things can be created in Ruby, but Python has them built in. Nice.

Python:

class myDecorator(object):

def __init__(self, f):
print "inside myDecorator.__init__()"
f()

def __call__(self):
print "inside myDecorator.__call__()"

@myDecorator
def aFunction():
print "inside aFunction"

And which of these will get you a job?

Let's get one thing straight - if you're good at something, there is always a job for you. However, good is a measure of industry demand. Less demand means the bar for good is much higher when compared to more demand, where the definition of good is slightly lesser.

With that in mind, some basic trends analysis on Indeed.com, a job search engine says that the number of jobs postings on their site for ruby on rails is far more than the posting for Django, a popular web framework on Python. However, job searches for Python, the language, as a skill far outclasses Ruby. This tells us a few things.

Web or not 
By the looks of it, Python seems to be a more popular language than Ruby, but the demand for their corresponding web frameworks is vice versa. This could be also because Python is also a very popular backend language, as opposed to Ruby.

So where does that put you, the job seeker? Many people say that learning Python is easier than Ruby. But when it comes to the web frameworks, Ruby on Rails is very powerful and it does a lot of work for the developer, leaving the coder to think more about the business logic of the application being built.

I think at the end of the day, it's a call on whether you want to work completely on the web or do you want to work on backend code as well. If you want to work only on the web, then you might have a better chance of landing a job with Ruby, as you can learn Ruby on Rails with relative ease after that. Python, on the other hand, can get you a lot of backend jobs and if you put in the time to learn Django, you can work on web applications also.

Source: HOB