What does Ruby have that Python doesn't, and vice versa?
Asked Answered
G

36

263

There is a lot of discussions of Python vs Ruby, and I all find them completely unhelpful, because they all turn around why feature X sucks in language Y, or that claim language Y doesn't have X, although in fact it does. I also know exactly why I prefer Python, but that's also subjective, and wouldn't help anybody choosing, as they might not have the same tastes in development as I do.

It would therefore be interesting to list the differences, objectively. So no "Python's lambdas sucks". Instead explain what Ruby's lambdas can do that Python's can't. No subjectivity. Example code is good!

Don't have several differences in one answer, please. And vote up the ones you know are correct, and down those you know are incorrect (or are subjective). Also, differences in syntax is not interesting. We know Python does with indentation what Ruby does with brackets and ends, and that @ is called self in Python.

UPDATE: This is now a community wiki, so we can add the big differences here.

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.

An example:

class Kaka
  puts self
end

self in this case is the class, and this code would print out "Kaka". 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 of a rails extension:

class String
  def starts_with?(other)
    head = self[0, other.length]
    head == other
  end
end

Python (imagine there were no ''.startswith 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.

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 in to the language.

Ruby has blocks

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 { |here|
    many=lines+of+code
    goes(here)
}

Python (Ruby blocks correspond to different constructs in Python):

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

Or

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

Or

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

amethod(function)     # `function` is a callback

Interestingly, the convenience statement in Ruby for calling a block is called "yield", which in Python will create a generator.

Ruby:

def themethod
    yield 5
end

themethod do |foo|
    puts foo
end

Python:

def themethod():
    yield 5

for foo in themethod():
    print foo

Although the principles are different, the result is strikingly similar.

Ruby supports functional style (pipe-like) programming more easily

myList.map(&:description).reject(&:empty?).join("\n")

Python:

descriptions = (f.description() for f in mylist)
"\n".join(filter(len, descriptions))

Python has built-in generators (which are used like Ruby blocks, as noted above)

Python has support for generators in the language. In Ruby 1.8 you can use the generator module which uses continuations to create a generator from a block. Or, you could just use a block/proc/lambda! Moreover, in Ruby 1.9 Fibers are, and can be used as, generators, and the Enumerator class is a built-in generator 4

docs.python.org has this generator example:

def reverse(data):
    for index in range(len(data)-1, -1, -1):
        yield data[index]

Contrast this with the above block examples.

Python has flexible name space 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 Rubys 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 themodule import *, thereby polluting the namespace if you want. But you can also import just selected names with from themodule import aname, another or you can simply import themodule and then access the names with themodule.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

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 frobnicate(bar):
    """frobnicate takes a bar and frobnicates it

       >>> bar = Bar()
       >>> bar.is_frobnicated()
       False
       >>> frobnicate(bar)
       >>> bar.is_frobnicated()
       True
    """

Ruby's equivalent are similar to javadocs, and located above the method instead of within it. They can be retrieved at runtime from the files by using 1.9's Method#source_location example use

Python has multiple inheritance

Ruby does not ("on purpose" -- see Ruby's website, see here how it's done in Ruby). It does reuse the module concept as a type of abstract classes.

Python has list/dict comprehensions

Python:

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

Ruby:

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

Python:

>>> (x*x for x in range(10))
<generator object <genexpr> at 0xb7c1ccd4>
>>> list(_)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Ruby:

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

Python 2.7+:

>>> {x:str(y*y) for x,y in {1:2, 3:4}.items()}
{1: '4', 3: '16'}

Ruby:

>> Hash[{1=>2, 3=>4}.map{|x,y| [x,(y*y).to_s]}]
=> {1=>"4", 3=>"16"}

Python has decorators

Things similar to decorators can also be created in Ruby, and it can also be argued that they aren't as necessary as in Python.

Syntax differences

Ruby requires "end" or "}" to close all of its scopes, while Python uses white-space only. There have been recent attempts in Ruby to allow for whitespace only indentation http://github.com/michaeledgar/seamless

Gamber answered 11/7, 2009 at 12:24 Comment(18)
Yeah, I thought this was a better idea, but that would have required people to actually read the question first. :-D So I changed it, it's community wiki now.Gamber
With regards to multiple inheritance, saying just "Ruby does not" is disingenuous. I can not think of anything you can do in Python with multiple inheritance that you can't do in ruby with modules/"mixin inheritance". (It's even arguable that including modules just plain is multiple inheritance.)Buitenzorg
That you can do the same thing some other way is an argument that doesn't hold. You can do everything here some other way. And since modules aren't classes, it's not multiple inheritance. You are welcome to contribute code examples of how it's done in Pythons multiple inheritence vs with Rubys modules.Gamber
Modules aren't Classes but Classes are Modules. % ruby -e 'p Class < Module' trueBuitenzorg
It's worth noting that the lack of parens in Ruby allows for more declarative-looking constructs. For example, Rails declares relationships as has_many :things, which would look more awkward. And things that looks like special syntax, like Ruby's require (equivalent of import) and attr_accessor, are actually just method calls.Gynecic
@Chuck, good point, and yet another example of the differing attitudes between the languages. Python sees that as implicit magick. If it is a method call, it should look like a method call. But, that's subjective territory again.Gamber
Lennart, you would dislike Scala then...Scala has an even more flexible syntax than Ruby :)Hammerless
-1 Unfortunately, this question misses its goal and most of the purported differences aren't differences at all and misinformation abounds!Roughhouse
@bias: Could you provide a couple of examples of "misinformation" in the question?Molehill
Nvm I can't post code in a comment :/Apparatus
@Davidmoreen I believe you can short code snippets in comments using the backquote character eg this is some codeFardel
Module includes are in fact multiple inheritance, not just in concept but in actual implementation in the Ruby interpreter. When a Ruby module is included, it is injected into the inheritance chain exactly the same way that superclasses are. Method resolution is the same. In Ruby multiple module includes are multiple inheritance. Anyone who wants to contest this as semantically "not the same thing" as multiple inheritance is just being pedantic. What's the point of something not being the "same thing" if the effect is identical and just as easily achieved? A distinction without a difference.Byway
“In Python, the file is a module, and you can import its contained names with from themodule import * – In fact, you can even tell a module, which properties should be importable and included in *, by specifying a module's __all__ list.Fitch
@Close voter: Why the vote to close?Flux
@Andrew: apparently because it's "not a real question" (I didn't vote to close, I just checked why the voter did). I can see why, it is a very broad, potentially subjective, question that's hard to answer succinctly.Gunilla
Nowadays there is programmers.SE, but when this question was posed, it was on-topic here.Gamber
It is most definitely neither subjective, nor argumentative. It's an objective list of differences, not a "better or worse". It's also very helpful. The closing is mistaken and it should be reopened.Gamber
The popularity of the ruby over python is because of RubyOnRails web framework. The framework is so flexible and easy to learn and it helps you to create running application in just few minutes.Murmansk
G
5

You can have code in the class definition in both Ruby and Python. However, in Ruby you have a reference to the class (self). In Python you don't have a reference to the class, as the class isn't defined yet.

An example:

class Kaka
  puts self
end

self in this case is the class, and this code would print out "Kaka". There is no way to print out the class name or in other ways access the class from the class definition body in Python.

Gamber answered 11/7, 2009 at 12:26 Comment(12)
Can you provide more details (like code) for your first point?Cobalt
Example code is a good idea, I added that, even though this case is trivial.Gamber
@SilentGhost: I can't think of one that isn't really obscure right now. :)Gamber
you can access the class name inside the class in python: class foo(): def init__(self): print self.__class.__name__Strawn
@txwikinger: yeah, but not within the class' body, which is executed at the same time as the class statement.Gripsack
You can define class methods in python whose first parameter, conventionally called 'cls', refers to the class like self refers to instances in instance methods.Sherrilsherrill
True. I would be really interested in seeing a case where this is a useful convenience. Seems to me like when you are defining the class, you'd know its name and other attributes you'd be putting in there and so would already have whatever you'd use the class reference for... Anybody??Sherrilsherrill
Well, it can be used as a prettier syntax for thinks like the Zope component architectures implements(Interface), instead of for example __implements__ = (Interface). Although that's possible in Python as well (obviously as Zope runs on Python) but only involving some heavy magic using metaclasses and modification of locals().Gamber
You can print the class name in Python, try this in your class definition body: print inspect.getframeinfo(inspect.currentframe())[2]Buchalter
@truppo: Sure, but the name isn't useful, you need that class object so you can modify it.Gamber
This is still the feature in Ruby I miss most in Python. So I accept this as an answer, so Stack overflow stops nagging me that I should accept an answer. :)Gamber
instead of typing puts self can we use puts 'Kaka'Pasteurism
D
34

Ruby has the concepts of blocks, which are essentially syntactic sugar around a section of code; they are a way to create closures and pass them to another method which may or may not use the block. A block can be invoked later on through a yield statement.

For example, a simple definition of an each method on Array might be something like:

class Array
  def each
    for i in self  
      yield(i)     # If a block has been passed, control will be passed here.
    end  
  end  
end  

Then you can invoke this like so:

# Add five to each element.
[1, 2, 3, 4].each{ |e| puts e + 5 }
> [6, 7, 8, 9]

Python has anonymous functions/closures/lambdas, but it doesn't quite have blocks since it's missing some of the useful syntactic sugar. However, there's at least one way to get it in an ad-hoc fashion. See, for example, here.

Depositor answered 11/7, 2009 at 12:32 Comment(15)
That last line would in Python be [print e+5 for e in [1,2,3,4]] so this example is unclear. It looks like Python has it...Gamber
@Lennart: apart from your example just beeing horrible it is syntactically wrong, too.Sashenka
@Lennart: I'm not sure that that's equivalent to a block. Consider the somewhat more torturous machinations you'd have to go through, for example, if you wanted to replicate not "each" but some other method. Getting "yield" is significantly harder.Depositor
To me it looks like you can do the same thing in Python by explicitly passing a callable to the method. Am I wrong?Gripsack
@unbeknow: A, right. But if that had been a function instead of a print, it would have worked. In python 3 this works: [print(e+5) for e in [1,2,3,4]] And when it comes to horribleness, I think the ruby code above is horrible, so that's clearly subjective and thereby not a part of this question. @John I'm not saying it's equivalent, I'm saying it's not obvious what the difference is from your example. @Bastien, no, but that you can do similar things doesn't mean they are the same. Differences here should be listed even if there are otehr ways to do it.Gamber
Well, I can't comment on the ruby code, I'm only a Python programmer. But what I want to point out is that even when some things are syntactically allowed you better don't do them (like using a functional construct like a list comprehension for the side effects). The reason may be the community that frowns on it or general software development principles that forbid it. So the OPs question for features that A has and B has not might be a little bit misleading in practice because nobody is using this feature in A either.Sashenka
Well, they are, but I think that in the Ruby community it's seen as "beautiful" but in the Python community as "ugly". But the point of this is to document the differences. And the current example code really doesn't have any differences, except that Ruby calls it's closures "blocks" and Python doesn't. So I'm still curious about the actual difference.Gamber
I'm a Python Programmer. I would like to see an example of how Ruby blocks help you to write something more concisely or more beautiful than with Python because it has not blocks. Your example could be written: for i in [1, 2, 3, 4]: print(i + 5). It doesn't use blocks, but its concise and beautiful as well as the ruby each example.Governess
Still no example of this. I removed the "block" part as this seems to not be an actual difference, just a concept in Ruby that nobody talks about in Python.Gamber
Those are just anonymous functions. Why try to give them another name and pass as something new?Cavazos
@lennart, I'm definitely not a Python programmer, but I've often wondered how things like Sinatra(sinatrarb.com) would be accomplished without blocks.Vitriol
@Manuel, procs are useful for attaching functors to non-trivial data structures (trees, graphs...) which can't be 'for-looped' and hence require special iterators to transverse. Blocks, which are anonymous procs, let you implement the functor in one expression (vs. define then implement) which dramatically speeds up the process of coding and clarifies intent. E.g. if you were creating a graph data structure you could define one 'each' iterator and then mixin Enumerable which would instantly give you access to dozens of iterators (sort, all?, any?, grep). Now you call a block ...Roughhouse
@RommeDeSerieux, because it needs a name in the language! Moreover, it's a function object, not a function. Let's look at the Ruby Docs: "Proc objects are blocks of code that have been bound to a set of local variables" so an anonymous Proc is just the block and it's certainly not just a function!Roughhouse
@RommeDeSerieux: They're anonymous functions, yes, but the difference from Ruby blocks and Python lambdas is that blocks are not first-class citizens. Contrary to the "everything is an object" philosophy that seems to otherwise pervade Ruby, blocks are not objects and you have to box them and unbox them. For some interesting details see innig.net/software/ruby/closures-in-ruby.rb and https://mcmap.net/q/111042/-ruby-convert-proc-to-lambdaSplenomegaly
@Vojislav Stojkovic: Thanks, i didn't know that. What do you think, that peculiarity of blocks a good thing?Cavazos
R
28

Python Example

Functions are first-class variables in Python. You can declare a function, pass it around as an object, and overwrite it:

def func(): print "hello"
def another_func(f): f()
another_func(func)

def func2(): print "goodbye"
func = func2

This is a fundamental feature of modern scripting languages. JavaScript and Lua do this, too. Ruby doesn't treat functions this way; naming a function calls it.

Of course, there are ways to do these things in Ruby, but they're not first-class operations. For example, you can wrap a function with Proc.new to treat it as a variable--but then it's no longer a function; it's an object with a "call" method.

Ruby's functions aren't first-class objects

Ruby functions aren't first-class objects. Functions must be wrapped in an object to pass them around; the resulting object can't be treated like a function. Functions can't be assigned in a first-class manner; instead, a function in its container object must be called to modify them.

def func; p "Hello" end
def another_func(f); method(f)[] end
another_func(:func)      # => "Hello"

def func2; print "Goodbye!"
self.class.send(:define_method, :func, method(:func2))
func                     # => "Goodbye!"

method(:func).owner      # => Object
func                     # => "Goodbye!"
self.func                # => "Goodbye!"    
Roughhouse answered 11/7, 2009 at 12:24 Comment(15)
You're badly confused. First-class objects are assigned by assignment: x = y, not by calling self.class.send(:define_method, :func, method(:func2)). Your "counterexample" shows just how Ruby's functions are not first-class. If you disagree, feel free to post your own answer; don't stick your confusion in mine.Iatry
@banister: I think it's fair to say that Common Lisp functions aren't quite first-class. Compare Scheme. As for Scala, I think Scala functions are first-class, while methods are not; but it's super easy to wrap a method as a function.Tempe
In scala, a function call is just syntactic sugar for the apply method of an object. Any object that defines an apply() method is a "function" and can be called using obj() or obj.apply(). A function def is just a shorthand for defining an object with an apply method.Counsellor
Things defined by def ... end in ruby aren't functions. They're methods (the way you've defined them, of Kernel). Methods can be unbound (using the #method method), which are then objects. The closest thing ruby has to functions are Proc instances, which are also objects, and can be passed around or invoked. It also has a special syntax for passing a single callback Proc to a method, as John Feminella discusses in his answer.Vierra
@rampion: Functions are blocks of code with a single entry point that can take parameters and return values. Methods are a type of function. Ruby doesn't get to redefine functions in order to pretend it's more special than everyone else, or as an excuse for how poorly it handles them. That's just hand-waving.Iatry
@Glenn: I get what you're saying, but I'd quibble with the assertion that Ruby's redefining functions - methods are a separate semantic concept. If you want to play the definition game, most imperative code is procedures, not functions. I'm not trying to be difficult, it's just that I believe definitions and exactness are important. I'll agree that manipulating an UnboundMethod can be a PITA, tho.Vierra
@rampion: I don't agree, but it's irrelevant: your semantics don't make the end result any prettier.Iatry
@Glenn: Beauty is in the eye of the beholder. Nonetheless, methods are first-class objects by fulfilling the definition (in this case I'm referring to the Wikipedia definition). Maybe, you have some other definition of first-class? Do they need a Platinum Frequent Flier Card to get bumped up to first-class?Roughhouse
So long as this answer has my name on the front, you will not edit it to say something entirely different than what I said. That's blatent misattribution. Submit your own answer if you like. From your comment you're obviously trolling, so I'm not discussing anything with you.Iatry
@Glenn Check out the SO FAQ section "Other people can edit my stuff?!" - this is a Community Wiki.Roughhouse
@Glenn I edited the post so that people know what you posted vs. what I posted. I also added a synopsis of the disagreement. This is an objective language issue, let's not turn this subjective and into a flame/rollback war.Roughhouse
You are editing this to replace a position you don't like with your own; that's inappropriate editing. Again, and for the last time, if you wish to do that, add your own answer. I won't keep repeating myself; repeat this childish edit again and it will be reverted without comment. The "Add another answer" button is right there at the bottom.Iatry
This is a community wiki. I never remove or modified your information. To respect your post I added supplement information (which you have removed and modified). I linked to references and gave a synopsis of our differences (you don't justify your position). You have called me names and have been offensive - I'm reporting your behavior to SO admins.Roughhouse
You've repeatedly edited my answer to be partial to your pet language, and you've generally acted immature for the sake of continually wasting my time on an answer I supplied months ago and have no desire to repeatedly return to. I suspect the SO admins will appreciate your wasting their time as much as I appreciate you wasting mine. Grow up.Iatry
@bias: Methods are first-class objects, but they are merely wrappers around blocks, which are not first-class objects. Block is the underlying, fundamental concept that represents a function in Ruby. Because it's not an object, you always have to box it and unbox it, by wrapping it in a Proc (lambda or not) or a Method. And then, when you want to pass a Proc or a Method to code that expects a block (either explicitly declared with & or implicitly used with yield), then you have to unbox it by using the & operator.Splenomegaly
G
26

Ultimately all answers are going to be subjective at some level, and the answers posted so far pretty much prove that you can't point to any one feature that isn't doable in the other language in an equally nice (if not similar) way, since both languages are very concise and expressive.

I like Python's syntax. However, you have to dig a bit deeper than syntax to find the true beauty of Ruby. There is zenlike beauty in Ruby's consistency. While no trivial example can possibly explain this completely, I'll try to come up with one here just to explain what I mean.

Reverse the words in this string:

sentence = "backwards is sentence This"

When you think about how you would do it, you'd do the following:

  1. Split the sentence up into words
  2. Reverse the words
  3. Re-join the words back into a string

In Ruby, you'd do this:

sentence.split.reverse.join ' '

Exactly as you think about it, in the same sequence, one method call after another.

In python, it would look more like this:

" ".join(reversed(sentence.split()))

It's not hard to understand, but it doesn't quite have the same flow. The subject (sentence) is buried in the middle. The operations are a mix of functions and object methods. This is a trivial example, but one discovers many different examples when really working with and understanding Ruby, especially on non-trivial tasks.

Gastric answered 11/7, 2009 at 12:24 Comment(1)
I agree. Ruby seems to flow naturally when I write it, so "zenlike" is a good term.Jockey
A
18

You can import only specific functions from a module in Python. In Ruby, you import the whole list of methods. You could "unimport" them in Ruby, but it's not what it's all about.

EDIT:

let's take this Ruby module :


module Whatever
  def method1
  end

  def method2
  end
end

if you include it in your code :


include Whatever

you'll see that both method1 and method2 have been added to your namespace. You can't import only method1. You either import them both or you don't import them at all. In Python you can import only the methods of your choosing. If this would have a name maybe it would be called selective importing?

Aboutship answered 11/7, 2009 at 12:24 Comment(9)
Oh, right! Python likes namespaces. Isn't that the case in Ruby? You don't import bla; bla.foo() in Ruby?Gamber
You can import only function a, not all the functions inside. If for example you include a Ruby module that declares 3 non-static functions, you get them all included in your namespace. In python you'd have to write from module import *.Cortezcortical
Doesn't that lead to a lot of namespace clutter?Gamber
Are you referring to Ruby's module importing system?Cortezcortical
@Cortezcortical yes, that's what I'm referring to.Gamber
I think it does. That's what I hate about Ruby modules.Cortezcortical
Ruby doesn't really have a module system in the same sense as python. require works basically as textual inclusion with some checks for dupilicate inclusion baked in. You can (ab)use modules as namespaces but module is actually a bit of a misnomer. Modules are basically classes sans the new, allocate methods. They work best as a way to share code on a per class/object basis, not as mechanism for partitioning libraries, or to share code across programs.Buitenzorg
you can selectively add in ruby: eigenclass.org/hiki/…Denaturalize
you can also use ruby-doc.org/stdlib/libdoc/forwardable/rdoc/index.html in RubyDenaturalize
E
18

Python has a "we're all adults here" mentality. Thus, you'll find that Ruby has things like constants while Python doesn't (although Ruby's constants only raise a warning). The Python way of thinking is that if you want to make something constant, you should put the variable names in all caps and not change it.

For example, Ruby:

>> PI = 3.14
=> 3.14
>> PI += 1
(irb):2: warning: already initialized constant PI
=> 4.14

Python:

>>> PI = 3.14
>>> PI += 1
>>> PI
4.1400000000000006
Eisenach answered 11/7, 2009 at 14:54 Comment(13)
Do you like this(python) way of thinking yourself? Just curious.Furiya
My subjective opinion on the issue is that I never understood why some languages have lots of features that prevent me from doing things. I love that Python doesn't try to stop me from doing what I need. But again, that's subjective, and hence OT. ;)Gamber
Ha.. this just reminds me that at least in python 2.*, you were able to do "True, False = False, True"... I believe they have correctly fixed that in python 3.0... that's something you should be prevented from doing.Monostome
Personally, I like strict guidelines enforced by the language because it makes all code written in that language consistent. It forces you to follow the guidelines, and developers reading your code can tell at a glance what's what. While most Python coders use the same general "style", I've seen some pretty big inconsistencies that wouldn't be possible in Ruby.Sair
@Tom: Yeah True and False are just builtin bool instances. :) In python 3 they added them to keywords as well, so you can't create new variables with those names. @musicfreak: I don't mind STYLE enforcements. After all, that's what Python indentation is.;-) It's things like private methods and things I don't like. I can often just stop reasonable code reuse, for example.Gamber
@Lennart: Ah, I see. Well in that case I see where you're coming from. :)Sair
What I hate is that you aren't forced to call the super class constructor. Sometimes it results in errors that are difficult to find.Gripsack
@Lennart What? You can use private methods in ruby - just use reflection! Private just hides methods from accidental usage (like the cover flap over a trigger on missile launcher - some times it is good to make sure people actually want to do something). Really, all the anti-Ruby arguments seem to stem from a lack of understanding Ruby.Roughhouse
-1 It seems like adults make judicious decisions that are informed and that only children make changes without concern for the consequences. Ruby informs you that you are doing something weird, and since you are an informed adult it lets you make that change.Roughhouse
@Roughhouse - I'm not sure why you're downvoting me. This answer doesn't agree or disagree with the python way of doing things. It's just a statement of fact.Eisenach
@Jason "we're all adults here" is a statement of a fact? I'd like to call that an opinion wrapped around a feature, hence the down vote.Roughhouse
@Roughhouse - Saying "we're all adults here" wasn't meant as a slight. It's an unofficial Python motto, which I believe is best explained here: mail.python.org/pipermail/tutor/2003-October/025932.htmlPlacencia
@bias: Yes it is a statement of fact.Gamber
D
16

From Ruby's website:

Similarities As with Python, in Ruby,...

  • There’s an interactive prompt (called irb).
  • You can read docs on the command line (with the ri command instead of pydoc).
  • There are no special line terminators (except the usual newline).
  • String literals can span multiple lines like Python’s triple-quoted strings.
  • Brackets are for lists, and braces are for dicts (which, in Ruby, are called “hashes”).
  • Arrays work the same (adding them makes one long array, but composing them like this a3 = [ a1, a2 ] gives you an array of arrays).
  • Objects are strongly and dynamically typed.
  • Everything is an object, and variables are just references to objects.
  • Although the keywords are a bit different, exceptions work about the same.
  • You’ve got embedded doc tools (Ruby’s is called rdoc).

Differences Unlike Python, in Ruby,...

  • Strings are mutable.
  • You can make constants (variables whose value you don’t intend to change).
  • There are some enforced case-conventions (ex. class names start with a capital letter, variables start with a lowercase letter).
  • There’s only one kind of list container (an Array), and it’s mutable.
  • Double-quoted strings allow escape sequences (like \t) and a special “expression substitution” syntax (which allows you to insert the results of Ruby expressions directly into other strings without having to "add " + "strings " + "together"). Single-quoted strings are like Python’s r"raw strings".
  • There are no “new style” and “old style” classes. Just one kind.
  • You never directly access attributes. With Ruby, it’s all method calls.
  • Parentheses for method calls are usually optional.
  • There’s public, private, and protected to enforce access, instead of Python’s _voluntary_ underscore __convention__.
  • “mixin’s” are used instead of multiple inheritance.
  • You can add or modify the methods of built-in classes. Both languages let you open up and modify classes at any point, but Python prevents modification of built-ins — Ruby does not.
  • You’ve got true and false instead of True and False (and nil instead of None).
  • When tested for truth, only false and nil evaluate to a false value. Everything else is true (including 0, 0.0, "", and []).
  • It’s elsif instead of elif.
  • It’s require instead of import. Otherwise though, usage is the same.
  • The usual-style comments on the line(s) above things (instead of docstrings below them) are used for generating docs.
  • There are a number of shortcuts that, although give you more to remember, you quickly learn. They tend to make Ruby fun and very productive.
Dilks answered 11/7, 2009 at 12:24 Comment(2)
"It’s require instead of import. Otherwise though, usage is the same." Seems to be completely inaccurate.Connotation
There are also Sets in Ruby that people rarely use, but they are built in. So I can say, stuff_in_backpack = Set.new; stuff_in_backpack << "computer"; stuff_in_backpack << "shoes"; # and the set will hold all the values without guaranteeing order.Dominations
J
12

I'd like to suggest a variant of the original question, "What does Ruby have that Python doesn't, and vice versa?" which admits the disappointing answer, "Well, what can you do with either Ruby or Python that can't be done in Intercal?" Nothing on that level, because Python and Ruby are both part of the vast royal family sitting on the throne of being Turing approximant.

But what about this:

What can be done gracefully and well in Python that can't be done in Ruby with such beauty and good engineering, or vice versa?

That may be much more interesting than mere feature comparison.

Jato answered 11/7, 2009 at 12:24 Comment(1)
a comment at best. still my +1Shofar
A
12

What Ruby has over Python are its scripting language capabilities. Scripting language in this context meaning to be used for "glue code" in shell scripts and general text manipulation.

These are mostly shared with Perl. First-class built-in regular expressions, $-Variables, useful command line options like Perl (-a, -e) etc.

Together with its terse yet epxressive syntax it is perfect for these kind of tasks.

Python to me is more of a dynamically typed business language that is very easy to learn and has a neat syntax. Not as "cool" as Ruby but neat. What Python has over Ruby to me is the vast number of bindings for other libs. Bindings to Qt and other GUI libs, many game support libraries and and and. Ruby has much less. While much used bindings e.g. to Databases are of good quality I found niche libs to be better supported in Python even if for the same library there is also a Ruby binding.

So, I'd say both languages have its use and it is the task that defines which one to use. Both are easy enough to learn. I use them side-by-side. Ruby for scripting and Python for stand-alone apps.

Alectryomancy answered 11/7, 2009 at 13:41 Comment(4)
Question from someone who does not yet know Ruby: What do you mean by "$-Variables"? Do you mean global variables? If so, in Python, a variable defined in a module outside of a class or function is global. If not - what's the distinction?Sherrilsherrill
Anon: if you declare a $variable anywhere in the code it is global because of the prefix. Thus, it doesn't matter where it is defined it is always global, and is always known as such.Fullfaced
Not exactly, actually I meant pre-defined variables like $_, $1 etc. These are autmatically filled with values by ruby itself. $_ is the last line read. $1, $2, etc. are the regular expression matches from the last match. See here for a complete list: zenspider.com/Languages/Ruby/QuickRef.html#17 It basically is a hack for compact scripts. You can get all the info via API calls too, but using $ variables it more terse. Such kind of variables just doesn't suit Python's style, they deliberately left them out.Alectryomancy
Thanks for that zenspider link - had been looking for something like that for a quick (non-tutorial) feel for Ruby.Sherrilsherrill
G
12

I don't think "Ruby has X and Python doesn't, while Python has Y and Ruby doesn't" is the most useful way to look at it. They're quite similar languages, with many shared abilities.

To a large degree, the difference is what the language makes elegant and readable. To use an example you brought up, both do theoretically have lambdas, but Python programmers tend to avoid them, and constructs made using them do not look anywhere near as readable or idiomatic as in Ruby. So in Python, a good programmer will want to take a different route to solving the problem than he would in Ruby, just because it actually is the better way to do it.

Gynecic answered 11/7, 2009 at 14:52 Comment(16)
I agree that lambdas have limited scope and aren't useful in many cases. However, I don't think it's fair to say that Python programmers avoid them like the plague.Eisenach
I agree that lambdas are used often with Python - like with map, filter, reduce. The big difference seems to be that Python lambdas are limited to expressions whereas Ruby blocks can be multiline and involve statements. My general impression from what I've read about Ruby is that this feature in particular makes Rubyists go for the DSL approach, whereas Pythonistas are more likely to go for creating API's. My info on Ruby is still very superficial though.Sherrilsherrill
@Anon: I've looked high and low for example of anonymous multiline blocks in Ruby. If you can do them, then nobody (sensibly) seem to actually do it. Any example?Gamber
@Lennart: Multiline blocks are used all the time in Ruby -- more often than I see lambdas used in idiomatic Python code, actually. For a common example, see info.michael-simons.eu/2007/08/06/rails-respond_to-method.Gynecic
Since I'm not a Ruby programmer, I'm glad Chuck responded. While looking out there for examples, I found this interesting proposal for Ruby-style blocks in Python: tav.espians.com/ruby-style-blocks-in-python.htmlSherrilsherrill
@Chuck: I don't get it. As far as I can tell respond do |format| requires respond to use yield. Is that incorrect? If it uses yield, then that statement is as far as I can see pretty much equivalent to for format in respond_to(): . So again I fail to see what these magick "blocks" do that Python don't.Gamber
@Lennart: No, it does not use yield. (Ruby's yield is completely different from Python's anyway -- it does not return a generator.) It wouldn't be meaningful to write for format in respond_to(). The respond_to method doesn't return anything meaningful -- it simply responds to the current HTTP request. The do in respond_to do is the beginning of a block. In that block, we talk to a temporary object (labeled format in this example) that implements a very basic DSL for responding to an HTTP request.Gynecic
@Chuck, yeah I found the definition of respond_to now, and it actually takes a block argument and calls it. The other examples of blocks have used a yield. The respond_to example makes it clearer how blocks are used as anonymous functions. Yet, I completely fail to see how this can't be implemented just as elegantly with either generators or by simply passing a named function to do_respond. Both those cases are in any case evidently WAY easier to understand.Gamber
@Lennart: Um, OK. I just pointed to that as an example of a multiline block. I wasn't trying to prove anything else. (Also, as I said, Ruby's yield is completely unrelated to Python's yield. There's no difference between calling a block and calling yield.)Gynecic
It may be unrelated, but funnily enough, you use it in exactly the same way. :)Gamber
In the sense that both are called with an argument, yes, they're used the same way. In the sense that they do completely different things and are used in different cases, I'm not really sure I'd agree.Gynecic
No, really, every example I have seen of using a block can be replaced with a for x in generator(). It would work the same, and if you use yield in Ruby, it would even look the same! It's just a matter of view point. You claim the method calls the code block with parameters. Python claims the code block calls the method and gets parameters back. The actual differences are miniscule.Gamber
OK, seen places where a block isn't used in this way, but instead is passed into a class and stored there. In that case you need to define the block as a function in Python.Gamber
blocks can also be used to implement lazy evaluationHammerless
Can you 'mixin Enumerable' against a generator and instantly get 30 new and wonderful iterators? You need to look at the language in the whole before you understand why blocks/Procs are great.Roughhouse
Python doesn't have Enumerable, but generating 30 iterators in one go is not a problem.Gamber
C
11

Shamelessly copy/pasted from: Alex Martelli answer on "What's better about Ruby than Python" thread from comp.lang.python mailing list.

Aug 18 2003, 10:50 am Erik Max Francis wrote:

"Brandon J. Van Every" wrote:

What's better about Ruby than Python? I'm sure there's something. What is it?

Wouldn't it make much more sense to ask Ruby people this, rather than Python people?

Might, or might not, depending on one's purposes -- for example, if one's purposes include a "sociological study" of the Python community, then putting questions to that community is likely to prove more revealing of information about it, than putting them elsewhere:-).

Personally, I gladly took the opportunity to follow Dave Thomas' one-day Ruby tutorial at last OSCON. Below a thin veneer of syntax differences, I find Ruby and Python amazingly similar -- if I was computing the minimum spanning tree among just about any set of languages, I'm pretty sure Python and Ruby would be the first two leaves to coalesce into an intermediate node:-).

Sure, I do get weary, in Ruby, of typing the silly "end" at the end of each block (rather than just unindenting) -- but then I do get to avoid typing the equally-silly ':' which Python requires at the start of each block, so that's almost a wash:-). Other syntax differences such as '@foo' versus 'self.foo', or the higher significance of case in Ruby vs Python, are really just about as irrelevant to me.

Others no doubt base their choice of programming languages on just such issues, and they generate the hottest debates -- but to me that's just an example of one of Parkinson's Laws in action (the amount on debate on an issue is inversely proportional to the issue's actual importance).

Edit (by AM 6/19/2010 11:45): this is also known as "painting the bikeshed" (or, for short, "bikeshedding") -- the reference is, again, to Northcote Parkinson, who gave "debates on what color to paint the bikeshed" as a typical example of "hot debates on trivial topics". (end-of-Edit).

One syntax difference that I do find important, and in Python's favor -- but other people will no doubt think just the reverse -- is "how do you call a function which takes no parameters". In Python (like in C), to call a function you always apply the "call operator" -- trailing parentheses just after the object you're calling (inside those trailing parentheses go the args you're passing in the call -- if you're passing no args, then the parentheses are empty). This leaves the mere mention of any object, with no operator involved, as meaning just a reference to the object -- in any context, without special cases, exceptions, ad-hoc rules, and the like. In Ruby (like in Pascal), to call a function WITH arguments you pass the args (normally in parentheses, though that is not invariably the case) -- BUT if the function takes no args then simply mentioning the function implicitly calls it. This may meet the expectations of many people (at least, no doubt, those whose only previous experience of programming was with Pascal, or other languages with similar "implicit calling", such as Visual Basic) -- but to me, it means the mere mention of an object may EITHER mean a reference to the object, OR a call to the object, depending on the object's type -- and in those cases where I can't get a reference to the object by merely mentioning it I will need to use explicit "give me a reference to this, DON'T call it!" operators that aren't needed otherwise. I feel this impacts the "first-classness" of functions (or methods, or other callable objects) and the possibility of interchanging objects smoothly. Therefore, to me, this specific syntax difference is a serious black mark against Ruby -- but I do understand why others would thing otherwise, even though I could hardly disagree more vehemently with them:-).

Below the syntax, we get into some important differences in elementary semantics -- for example, strings in Ruby are mutable objects (like in C++), while in Python they are not mutable (like in Java, or I believe C#). Again, people who judge primarily by what they're already familiar with may think this is a plus for Ruby (unless they're familiar with Java or C#, of course:-). Me, I think immutable strings are an excellent idea (and I'm not surprised that Java, independently I think, reinvented that idea which was already in Python), though I wouldn't mind having a "mutable string buffer" type as well (and ideally one with better ease-of-use than Java's own "string buffers"); and I don't give this judgment because of familiarity -- before studying Java, apart from functional programming languages where all data are immutable, all the languages I knew had mutable strings -- yet when I first saw the immutable-string idea in Java (which I learned well before I learned Python), it immediately struck me as excellent, a very good fit for the reference-semantics of a higher level programming language (as opposed to the value-semantics that fit best with languages closer to the machine and farther from applications, such as C) with strings as a first-class, built-in (and pretty crucial) data type.

Ruby does have some advantages in elementary semantics -- for example, the removal of Python's "lists vs tuples" exceedingly subtle distinction. But mostly the score (as I keep it, with simplicity a big plus and subtle, clever distinctions a notable minus) is against Ruby (e.g., having both closed and half-open intervals, with the notations a..b and a...b [anybody wants to claim that it's obvious which is which?-)], is silly -- IMHO, of course!). Again, people who consider having a lot of similar but subtly different things at the core of a language a PLUS, rather than a MINUS, will of course count these "the other way around" from how I count them:-).

Don't be misled by these comparisons into thinking the two languages are very different, mind you. They aren't. But if I'm asked to compare "capelli d'angelo" to "spaghettini", after pointing out that these two kinds of pasta are just about undistinguishable to anybody and interchangeable in any dish you might want to prepare, I would then inevitably have to move into microscopic examination of how the lengths and diameters imperceptibly differ, how the ends of the strands are tapered in one case and not in the other, and so on -- to try and explain why I, personally, would rather have capelli d'angelo as the pasta in any kind of broth, but would prefer spaghettini as the pastasciutta to go with suitable sauces for such long thin pasta forms (olive oil, minced garlic, minced red peppers, and finely ground anchovies, for example - but if you sliced the garlic and peppers instead of mincing them, then you should choose the sounder body of spaghetti rather than the thinner evanescence of spaghettini, and would be well advised to forego the achovies and add instead some fresh spring basil [or even -- I'm a heretic...! -- light mint...] leaves -- at the very last moment before serving the dish). Ooops, sorry, it shows that I'm traveling abroad and haven't had pasta for a while, I guess. But the analogy is still pretty good!-)

So, back to Python and Ruby, we come to the two biggies (in terms of language proper -- leaving the libraries, and other important ancillaries such as tools and environments, how to embed/extend each language, etc, etc, out of it for now -- they wouldn't apply to all IMPLEMENTATIONS of each language anyway, e.g., Jython vs Classic Python being two implementations of the Python language!):

  1. Ruby's iterators and codeblocks vs Python's iterators and generators;

  2. Ruby's TOTAL, unbridled "dynamicity", including the ability
    to "reopen" any existing class, including all built-in ones, and change its behavior at run-time -- vs Python's vast but bounded dynamicity, which never changes the behavior of existing built-in classes and their instances.

Personally, I consider 1 a wash (the differences are so deep that I could easily see people hating either approach and revering the other, but on MY personal scales the pluses and minuses just about even up); and 2 a crucial issue -- one that makes Ruby much more suitable for "tinkering", BUT Python equally more suitable for use in large production applications. It's funny, in a way, because both languages are so MUCH more dynamic than most others, that in the end the key difference between them from my POV should hinge on that -- that Ruby "goes to eleven" in this regard (the reference here is to "Spinal Tap", of course). In Ruby, there are no limits to my creativity -- if I decide that all string comparisons must become case-insensitive, I CAN DO THAT! I.e., I can dynamically alter the built-in string class so that a = "Hello World" b = "hello world" if a == b print "equal!\n" else print "different!\n" end WILL print "equal". In python, there is NO way I can do that. For the purposes of metaprogramming, implementing experimental frameworks, and the like, this amazing dynamic ability of Ruby is extremely appealing. BUT -- if we're talking about large applications, developed by many people and maintained by even more, including all kinds of libraries from diverse sources, and needing to go into production in client sites... well, I don't WANT a language that is QUITE so dynamic, thank you very much. I loathe the very idea of some library unwittingly breaking other unrelated ones that rely on those strings being different -- that's the kind of deep and deeply hidden "channel", between pieces of code that LOOK separate and SHOULD BE separate, that spells d-e-a-t-h in large-scale programming. By letting any module affect the behavior of any other "covertly", the ability to mutate the semantics of built-in types is just a BAD idea for production application programming, just as it's cool for tinkering.

If I had to use Ruby for such a large application, I would try to rely on coding-style restrictions, lots of tests (to be rerun whenever ANYTHING changes -- even what should be totally unrelated...), and the like, to prohibit use of this language feature. But NOT having the feature in the first place is even better, in my opinion -- just as Python itself would be an even better language for application programming if a certain number of built-ins could be "nailed down", so I KNEW that, e.g., len("ciao") is 4 (rather than having to worry subliminally about whether somebody's changed the binding of name 'len' in the builtins module...). I do hope that eventually Python does "nail down" its built-ins.

But the problem's minor, since rebinding built-ins is quite a deprecated as well as a rare practice in Python. In Ruby, it strikes me as major -- just like the too powerful macro facilities of other languages (such as, say, Dylan) present similar risks in my own opinion (I do hope that Python never gets such a powerful macro system, no matter the allure of "letting people define their own domain-specific little languages embedded in the language itself" -- it would, IMHO, impair Python's wonderful usefulness for application programming, by presenting an "attractive nuisance" to the would-be tinkerer who lurks in every programmer's heart...).

Alex

Canfield answered 11/7, 2009 at 12:24 Comment(0)
D
11

Somewhat more on the infrastructure side:

  • Python has much better integration with C++ (via things like Boost.Python, SIP, and Py++) than Ruby, where the options seem to be either write directly against the Ruby interpreter API (which you can do with Python as well, of course, but in both cases doing so is low level, tedious, and error prone) or use SWIG (which, while it works and definitely is great if you want to support many languages, isn't nearly as nice as Boost.Python or SIP if you are specifically looking to bind C++).

  • Python has a number of web application environments (Django, Pylons/Turbogears, web.py, probably at least half a dozen others), whereas Ruby (effectively) has one: Rails. (Other Ruby web frameworks do exist, but seemingly have a hard time getting much traction against Rails). Is this aspect good or bad? Hard to say, and probably quite subjective; I can easily imagine arguments that the Python situation is better and that the Ruby situation is better.

  • Culturally, the Python and Ruby communities seem somewhat different, but I can only hint at this as I don't have that much experience interacting with the Ruby community. I'm adding this mostly in the hopes that someone who has a lot of experience with both can amplify (or reject) this statement.

Detumescence answered 11/7, 2009 at 12:24 Comment(3)
Your second point is at best misinformed. You should start by looking at Rack and SinatraAmphiarthrosis
I explicitly note that other Rails stacks exist; I just don't think anyone is actually using them. Checking Sinatra and Rack didn't exactly change that impression. Do you really think, say, Sinatra (94 SO questions total), or Camping (2 SO questions total), or any of the others, actually has a real userbase/community? Most of them don't even have real life users, as far as I can tell. Compare with Django (4K+) or Rails (7K+), or even web.py for that matter.Detumescence
Sinatra is actually rather popular for different, lightweight tasks due to its DSL. Its just less used because Rail's MVC provides more. Rails is actually built on Rack - That is what makes Phusion Passenger possible.Gales
L
11

"Variables that start with a capital letter becomes constants and can't be modified"

Wrong. They can.

You only get a warning if you do.

Lacerate answered 11/7, 2009 at 12:24 Comment(1)
If a language gives you a warning for an operation, it is my opinion that you very well can consider the operation "not possible". Anything else is madness.Connelly
P
11

Python has an explicit, builtin syntax for list-comprehenions and generators whereas in Ruby you would use map and code blocks.

Compare

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

to

res = (1..10).map{ |x| x*x }
Peeress answered 11/7, 2009 at 12:24 Comment(4)
how list comprehensions are not a plain Python? and there is a map function in Python as well.Restrain
But there is no list comprehension syntax in RubyPeeress
Python: res = map(lambda x: x*x, range(1,10))Bronchia
Python: res=map(2 .__rpow__, range(1,10))Knopp
S
9

Some others from:

http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/to-ruby-from-python/

(If I have misintrepreted anything or any of these have changed on the Ruby side since that page was updated, someone feel free to edit...)

Strings are mutable in Ruby, not in Python (where new strings are created by "changes").

Ruby has some enforced case conventions, Python does not.

Python has both lists and tuples (immutable lists). Ruby has arrays corresponding to Python lists, but no immutable variant of them.

In Python, you can directly access object attributes. In Ruby, it's always via methods.

In Ruby, parentheses for method calls are usually optional, but not in Python.

Ruby has public, private, and protected to enforce access, instead of Python’s convention of using underscores and name mangling.

Python has multiple inheritance. Ruby has "mixins."

And another very relevant link:

http://c2.com/cgi/wiki?PythonVsRuby

Which, in particular, links to another good one by Alex Martelli, who's been also posting a lot of great stuff here on SO:

http://groups.google.com/group/comp.lang.python/msg/028422d707512283

Sherrilsherrill answered 11/7, 2009 at 12:24 Comment(2)
In ruby you could simply freeze your array to change it to something immutableBesetting
Excellent post by Alex Martelli :)Joselow
G
8

I'm unsure of this, so I add it as an answer first.

Python treats unbound methods as functions

That means you can call a method either like theobject.themethod() or by TheClass.themethod(anobject).

Edit: Although the difference between methods and functions is small in Python, and non-existant in Python 3, it also doesn't exist in Ruby, simply because Ruby doesn't have functions. When you define functions, you are actually defining methods on Object.

But you still can't take the method of one class and call it as a function, you would have to rebind it to the object you want to call on, which is much more obstuse.

Gamber answered 11/7, 2009 at 12:24 Comment(9)
Ruby doesn't have functions at all. That said, TheClass.instance_method(:themethod).bind(anobject).call would be the equivalent ruby.Buitenzorg
Oh. So there is some sort of magic main class when you define a function that's not on an explicit class?Gamber
Yes, methods defined at the top level are private methods of Object.Buitenzorg
you can get a reference to a method, to store them in a object, by calling the "method" method.Cortezcortical
FWIW, it seems that in Python, functions and methods are actually the same type, and their different behavior comes from descriptors: users.rcn.com/python/download/….Gripsack
-1 Ruby has bound and unbound functions. Too much Ruby confusion!Roughhouse
@bias: And why would that mean a -1? It seems to me you just confirmed what I said.Gamber
The first comment shows that you can use an unbound method by binding it to an object just like in the Python example - so I don't get why this is a language difference. Moreover, The answer implies that in Python functions and methods are conceptually closer than in Ruby. But, in Ruby they are exactly the same thing!Roughhouse
But if you bind it to an object, then it's not unbound. Duh. :-) And they are the same thing in Python as well. It's just that Ruby doesn't actually have functions. And that means that my statement is correct. You can call an unbound method as if it was a function in Python. And that is actually useful, that means for example that you can call a method defined on a class on an object that doesn't have that class, which sometimes is useful.Gamber
V
7

I would like to mention Python descriptor API that allows one customize object-to-attribute "communication". It is also noteworthy that, in Python, one is free to implement an alternative protocol via overriding the default given through the default implementation of the __getattribute__ method. Let me give more details about the aforementioned. Descriptors are regular classes with __get__, __set__ and/or __delete__ methods. When interpreter encounters something like anObj.anAttr, the following is performed:

  • __getattribute__ method of anObj is invoked
  • __getattribute__ retrieves anAttr object from the class dict
  • it checks whether abAttr object has __get__, __set__ or __delete__ callable objects
  • the context (i.e., caller object or class, and value, instead of the latter, if we have setter) is passed to the callable object
  • the result is returned.

As was mentioned, this is the default behavior. One is free to change the protocol by re-implementing __getattribute__.

This technique is lot more powerful than decorators.

Viminal answered 11/7, 2009 at 12:24 Comment(0)
K
6

At this stage, Python still has better unicode support

Knopp answered 11/7, 2009 at 12:24 Comment(0)
P
6

Ruby has builtin continuation support using callcc.

Hence you can implement cool things like the amb-operator

Peeress answered 11/7, 2009 at 12:24 Comment(2)
I wish I understood callcc. Can you give a more mundane application scenario than McCarthy's Ambiguous Operator, to appreciate its merrits? I mean something real-world, not that funky CS stuff?!Cutthroat
"Funky CS stuff" is real. Take some time to learn: intertwingly.net/blog/2005/04/13/Continuations-for-CurmudgeonsFascination
B
5

My python's rusty, so some of these may be in python and i just don't remember/never learned in the first place, but here are the first few that I thought of:

Whitespace

Ruby handles whitespace completely different. For starters, you don't need to indent anything (which means it doesn't matter if you use 4 spaces or 1 tab). It also does smart line continuation, so the following is valid:

def foo(bar,
        cow)

Basically, if you end with an operator, it figures out what is going on.

Mixins

Ruby has mixins which can extend instances instead of full classes:

module Humor
  def tickle
    "hee, hee!"
  end
end
a = "Grouchy"
a.extend Humor
a.tickle    »   "hee, hee!"

Enums

I'm not sure if this is the same as generators, but as of Ruby 1.9 ruby as enums, so

>> enum = (1..4).to_enum
=> #<Enumerator:0x1344a8>

Reference: http://blog.nuclearsquid.com/writings/ruby-1-9-what-s-new-what-s-changed

"Keyword Arguments"

Both of the items listed there are supported in Ruby, although you can't skip default values like that. You can either go in order

def foo(a, b=2, c=3)
  puts "#{a}, #{b}, #{c}"
end
foo(1,3)   >> 1, 3, 3
foo(1,c=5) >> 1, 5, 3
c          >> 5

Note that c=5 actually assigns the variable c in the calling scope the value 5, and sets the parameter b the value 5.

or you can do it with hashes, which address the second issue

def foo(a, others)
  others[:b] = 2 unless others.include?(:b)
  others[:c] = 3 unless others.include?(:c)
  puts "#{a}, #{others[:b]}, #{others[:c]}"
end
foo(1,:b=>3) >> 1, 3, 3
foo(1,:c=>5) >> 1, 2, 5

Reference: The Pragmatic Progammer's Guide to Ruby

Bayonne answered 11/7, 2009 at 12:24 Comment(2)
Your second example foo(1,c=5) does not do what you think it does. Ruby does not have named parameters.Hammerless
Python has implicit line continuation inside brackets (, [ or {Incorporator
C
5

Ruby has a line by line loop over input files (the '-n' flag) from the commandline so it can be used like AWK. This Ruby one-liner:

ruby -ne 'END {puts $.}'

will count lines like the AWK one-liner:

awk 'END{print NR}'

Ruby gets feature this through Perl, which took it from AWK as a way of getting sysadmins on board with Perl without having to change the way they do things.

Clop answered 11/7, 2009 at 12:24 Comment(3)
I'd like to add that Python's command line support is rather weak. Besides the missing automatic loop you cannot put a couple of statements in a single line and pass it as a single-string command line argument to the interpreter. At least I failed to do so.Cutthroat
Of course you can. But you will (as with any otehr language) need to enclose is in quotes.Gamber
Python is not made to be used on the commandline, since you have to be explicit about some things (like sys.stdin) if you want to use it that way python -c "import sys; print len(list(sys.stdin))"Incorporator
G
5

You can have code in the class definition in both Ruby and Python. However, in Ruby you have a reference to the class (self). In Python you don't have a reference to the class, as the class isn't defined yet.

An example:

class Kaka
  puts self
end

self in this case is the class, and this code would print out "Kaka". There is no way to print out the class name or in other ways access the class from the class definition body in Python.

Gamber answered 11/7, 2009 at 12:26 Comment(12)
Can you provide more details (like code) for your first point?Cobalt
Example code is a good idea, I added that, even though this case is trivial.Gamber
@SilentGhost: I can't think of one that isn't really obscure right now. :)Gamber
you can access the class name inside the class in python: class foo(): def init__(self): print self.__class.__name__Strawn
@txwikinger: yeah, but not within the class' body, which is executed at the same time as the class statement.Gripsack
You can define class methods in python whose first parameter, conventionally called 'cls', refers to the class like self refers to instances in instance methods.Sherrilsherrill
True. I would be really interested in seeing a case where this is a useful convenience. Seems to me like when you are defining the class, you'd know its name and other attributes you'd be putting in there and so would already have whatever you'd use the class reference for... Anybody??Sherrilsherrill
Well, it can be used as a prettier syntax for thinks like the Zope component architectures implements(Interface), instead of for example __implements__ = (Interface). Although that's possible in Python as well (obviously as Zope runs on Python) but only involving some heavy magic using metaclasses and modification of locals().Gamber
You can print the class name in Python, try this in your class definition body: print inspect.getframeinfo(inspect.currentframe())[2]Buchalter
@truppo: Sure, but the name isn't useful, you need that class object so you can modify it.Gamber
This is still the feature in Ruby I miss most in Python. So I accept this as an answer, so Stack overflow stops nagging me that I should accept an answer. :)Gamber
instead of typing puts self can we use puts 'Kaka'Pasteurism
A
5

Python has docstrings and ruby doesn't... Or if it doesn't, they are not accessible as easily as in python.

Ps. If im wrong, pretty please, leave an example? I have a workaround that i could monkeypatch into classes quite easily but i'd like to have docstring kinda of a feature in "native way".

Auditorium answered 11/7, 2009 at 13:24 Comment(8)
doesnt have docstring, but, does have RDoc. So yes, not as easily accessible, but not 100% hidden.Bucovina
Ruby does not use docstrings. It does documentation in a different way.Gynecic
Omar: yes, i know about rdoc but afaik, they are not "as accessible" as as python's docstrings. For example, if i have a class and i want to output the rdoc documentation from within the class its pretty hefty job. What i have done is that i generate ri documentation which i try to keep up2date and then fetch that info vi ri itself. Definetly not up to the same level as python's docstrings..Auditorium
Docstrings can be used to provide doctests. Is there something like that for Ruby?Gamber
Yes, it's called "Ruby Doctest". As far as doctests are concerned, all that really matters is that you have readable documentation somewhere that includes testable code snippets -- it doesn't make a difference whether it's in a docstring or in a comment.Gynecic
Yeah, actually you are right, it doesn't matter for the doctest.Gamber
You can read Python's docstrings in the interactive interpreter with the 'help' built-in. I.e. each piece of code that provides docstrings automatically provides interactive help.Cutthroat
ThomasH: same sort of behaviour is infact available in ruby but what the missing feature that ruby doesnt is to have easy access to that same information during the execution of the code without first generating the "ri" documentation and querying from there..Auditorium
F
5

Ruby has sigils and twigils, Python doesn't.

Edit: And one very important thing that I forgot (after all, the previous was just to flame a little bit :-p):

Python has a JIT compiler (Psyco), a sightly lower level language for writing faster code (Pyrex) and the ability to add inline C++ code (Weave).

Fbi answered 11/7, 2009 at 15:1 Comment(13)
True, but that's just syntax.Gamber
Well, if you want to go down that road: both are Turing-complete. Everything else is just syntax.Predominate
Yes and a importax syntax difference ;-)Fbi
How is it important if you write @foo or self.foo?Gamber
@Jörg: OK, call it something else than "syntax" then. The point is that @foo and self.foo does the same thing, it's not actually a functionality Ruby has and Python doesn't.Gamber
@Lennart, The sigils are an annoying thing that Ruby has and Python hasn't :-pFbi
@fortran: which is a matter of taste.Gamber
@Lennart is a matter of readability, giving funny meanings for symbols when you can live perfectly without them only complicates things.Fbi
The word I'm looking for is "semantics" I think. It's just a name. If you think @foo or self.foo is more readable is still a matter of taste. I like the explicitness of self, and the way it make methods and functions be the same thing. Still, matters of taste.Gamber
I would also faviour conceptual differences of the languages for this question, rather than "pure" syntactial differences. What language construct does one language have and the other doesn't? But then, it's not so easy to draw the line. E.g. do standard libraries count? Does Python's 'functools' count when it comes to functional programming? And some "syntactic sugar" can make a whole lot of a difference in ease of reading and writing code. So I would be interested to learn what "sigils" and "twigils" are, and which impact they have on the code being written.Cutthroat
They are just those annoying (from my point of view, of course) symbols (one in case a of a sigil, two in case of a twigil) that you have to preppend to variable names to indicate it's type, scope or whatever was thinking the designer (depending on the language those meanings change and usualy are completely arbitrary, so that's why I don't like them).Fbi
Larry once claimed that Ruby has twigils, but if it does, I've never seen them used. I think that Larry might have meant that Ruby has sigils that indicate scoping, and that in Perl 6, twigils would be used for this same purpose. So essentially, Ruby has sigils, but not twigils.Zonation
how do you call this @@? it seems a twigil to meFbi
S
4

Syntax is not a minor thing, it has a direct impact on how we think. It also has a direct effect on the rules we create for the systems we use. As an example we have the order of operations because of the way we write mathematical equations or sentences. The standard notation for mathematics allows people to read it more than one way and arrive at different answers given the same equation. If we had used prefix or postfix notation we would have created rules to distinguish what the numbers to be manipulated were rather than only having rules for the order in which to compute values.

The standard notation makes it plain what numbers we are talking about while making the order in which to compute them ambiguous. Prefix and postfix notation make the order in which to compute plain while making the numbers ambiguous. Python would already have multiline lambdas if it were not for the difficulties caused by the syntactic whitespace. (Proposals do exist for pulling this kind of thing off without necessarily adding explicit block delimiters.)

I find it easier to write conditions where I want something to occur if a condition is false much easier to write with the unless statement in Ruby than the semantically equivalent "if-not" construction in Ruby or other languages for example. If most of the languages that people are using today are equal in power, how can the syntax of each language be considered a trivial thing? After specific features like blocks and inheritance mechanisms etc. syntax is the most important part of a language,hardly a superficial thing.

What is superficial are the aesthetic qualities of beauty that we ascribe to syntax. Aesthetics have nothing to do with how our cognition works, syntax does.

Soph answered 11/7, 2009 at 12:24 Comment(2)
This "comment" is three times as long as what's allowed in a comment, regardless of rep.Flux
This actually seems fine as an answer to me. Edited out the "this is a comment" bit.Hypothecate
A
3

Another difference in lambdas between Python and Ruby is demonstrated by Paul Graham's Accumulator Generator problem. Reprinted here:

Write a function foo that takes a number n and returns a function that takes a number i, and returns n incremented by i. Note: (a) that's number, not integer, (b) that's incremented by, not plus.

In Ruby, you can do this:

def foo(n)
  lambda {|i| n += i }
end

In Python, you'd create an object to hold the state of n:

class foo(object):
    def __init__(self, n):
        self.n = n
    def __call__(self, i):
        self.n += i
        return self.n

Some folks might prefer the explicit Python approach as being clearer conceptually, even if it's a bit more verbose. You store state like you do for anything else. You just need to wrap your head around the idea of callable objects. But regardless of which approach one prefers aesthetically, it does show one respect in which Ruby lambdas are more powerful constructs than Python's.

Argali answered 11/7, 2009 at 12:24 Comment(10)
You can't increment numbers in Python, so that restriction makes no sense. In Python numbers are immutable. If we change it to "plus" instead, the class is unnecessary. Hence this doesn't demonstrate anything about the lambda difference, but the difference in how numbers work. Unless of course you create a mutable number class. :)Gamber
The restriction is there to clarify the desired behavior. What the problem is asking for is: f = foo(10) f(2) >> 12 f(3) >> 15 ... lambda {|i| n + i } gives: f = foo(10) f(2) >> 12 f(3) >> 13 ... Numbers are immutable in Ruby as well -- you can't say 2 += 1 for instance. And n+=1 is fine in a regular Python function, but not a lambda. So it's a matter of what "n" is, the fact that it's created when the function is invoked and the lambda formed, that you can do assignment in a lambda (instead of just expressions), and that it can hold the value of n over multiple calls.Argali
I don't think you need to go to such lengths in Python. Functions can be defined within other functions. def foo(n): def f(i): return n + i return f.Artichoke
It's still not the same though, and your example is equivalent to the Python lambda in the comment above. The Ruby version creates a lambda which keeps state between calls. The example you posted lets you configure a starting value for n, but the function that foo returns will always have that start value. The Ruby version increments. So let's say f = foo(10). The Python version: f(1) => 11, f(1) => 11. The Ruby version f.call(1) => 11, f.call(1) => 12.Argali
def foo(n): L=[n] def f(i): L[0] += i return L[0] return f. In Python3 you could use nonlocal keyword.Molehill
@JF: Nice! I didn't realize you could do that. Thank you. Can you do straight up assignments in lambdas in Python3? I realize you just demonstrated it as a function, but I'm a lazy typist. ;-) Thanks again.Argali
@dormsbee: Assignment is a statement so you can't use it in lambdas (single expression). btw, if you use @full name: syntax then full name SO user is notified about your comment.Molehill
And in fact, you can do exactly the same thing in python as in the ruby example: def foo(n): return lambda i: i+n. f = foo(3); print f(7.0) will print 10.0. This answer do not demonstrate any difference at all.Gamber
@Lennart Regebro: It's not the same. Because with the code you've posted, invoking f(7) and then f(1) gives you 4. The point of the Accumulator problem is that it keeps state. So f(7) would give 10, but then saying f(1) after it would give 11. J.F. Sebastian's answer shows a way to get that functionality in Python without a wrapper class, though he still doesn't use a lambda because assignment can't happen in Python lambdas. I'm not claiming it's earth shattering power, but it is a difference in the way the languages treat lambdas.Argali
@dormsbee: OK, gotcha. Probably got it the first time I saw this as well. :) In any case it's not a difference in the lambdas, really. In Python assignments being a statement, and not an expression, return nothing, so even if n+=i was allowed in lambdas, it would return None.Gamber
M
3

Surprised to see nothing mentioned of ruby's "method missing" mechanism. I'd give examples of the find_by_... methods in Rails, as an example of the power of that language feature. My guess is that something similar could be implemented in Python, but to my knowledge it isn't there natively.

Mansoor answered 11/7, 2009 at 12:24 Comment(4)
Python has get_attribute, which accomplishes basically the same thing as Ruby's method_missing.Overliberal
Why do python developers always get so butt hurt when ruby is mentioned ANYWHERE? You can't deny this isn't true.Tutuila
method_missing can be emulated in Python in some cases: class M(): def __getattr__(self, n): return lambda: "Missing! " + n; M().hi(). However, there are slight differences and I doubt it's idiomatic in Python :-)Livi
@DJTripleThreat: I deny that it is true.Gamber
T
3

python has named optional arguments

def func(a, b=2, c=3):
    print a, b, c

>>> func(1)
1 2 3
>>> func(1, c=4)
1 2 4

AFAIK Ruby has only positioned arguments because b=2 in the function declaration is an affectation that always append.

Taphole answered 11/7, 2009 at 12:24 Comment(3)
what does "Ruby has only positioned arguments because b=2 in the function declaration is an affectation that always append" even mean?Hammerless
Dunno what planet you live on, but def my_method(param1, optional = false) works in Ruby 1.8.6, 1.8.7, and presumably 1.9!Fullfaced
The Wicked Flea, and people that upvoted his comment, you didn't look at the example close enough. He's able to skip the b parameter in the func call and it still maintains its default. That is, b is the second argument in the signature, but he can skip it by prefixing the second parameter with c=. Ruby uses hashes to simulate this, but it's not exactly the same.Kieger
D
2

In Ruby, when you import a file with require, all the things defined in that file will end up in your global namespace.

With Cargo you can "require libraries without cluttering your namespace".

# foo-1.0.0.rb
class Foo
  VERSION = "1.0.0"
end

# foo-2.0.0.rb
class Foo
  VERSION = "2.0.0"
end
>> Foo1 = import("foo-1.0.0")
>> Foo2 = import("foo-2.0.0")
>> Foo1::VERSION
=> "1.0.0"
>> Foo2::VERSION
=> "2.0.0"
Delaware answered 11/7, 2009 at 12:24 Comment(1)
This should rather have been a comment, not a new answer.Gamber
W
2

Ruby has embedded documentation:

 =begin

 You could use rdoc to generate man pages from this documentation

 =end
Willie answered 11/7, 2009 at 12:24 Comment(1)
The docstrings end up as a part of the methods/classes you set them on. So you can do help(class) and it will show you the docstrings, etc.Gamber
P
1

I like the fundamental differences in the way that Ruby and Python method invocations operate.

Ruby methods are invoked via a form "message passing" and need not be explicitly first-class functions (there are ways to lift methods into "proper" function-objects) -- in this aspect Ruby is similar to Smalltalk.

Python works much more like JavaScript (or even Perl) where methods are functions which are invoked directly (there is also stored context information, but...)

While this might seem like a "minor" detail it is really just the surface of how different the Ruby and Python designs are. (On the other hand, they are also quite the same :-)

One practical difference is the concept of method_missing in Ruby (which, for better or worse, seems to be used in some popular frameworks). In Python, one can (at least partially) emulate the behavior using __getattr__/__getattribute__, albeit non-idiomatically.

Pythagoreanism answered 11/7, 2009 at 12:24 Comment(1)
Really, the difference isn't as great as you describe. Ruby has closures (functions + contexts) all over, the difference is mostly how to get at them. You mentioned lifting methods in Ruby, but really the do / end blocks are far more pervasive an idiom. (Many people don't realize they're making a lambda function at first.) Another way of putting it: Ruby makes lambdas easy but function passing a bit awkward; Python makes function passing easy, but lambdas a bit awkward.Yuji
R
0

More about Ruby's blocks

It has being suggested that Ruby's blocks may be "substituted" by Python's context managers. In fact, blocks allow more than Python's context managers can do.

The receiving method of a block could execute the block within the context of some object, thus allowing the block to call methods otherwise unreacheable. Python's generators can't do that either.

A simple example may help:

class Proxy
   attr_accesor :target

   def method &block
      # Ruby 1.9 or in Rails 2.3
      target.instance_exec &block  
   end
end

class C
   private
   def hello
     puts "hello"
   end
end

p = Proxy.new
c = C.new
p.target = c
p.method { hello }

In this example the method call within the block { hello } has it true meaning in the context of the target object c.

This example is for illustrative purposes, only. Real working code that uses this kind of execute in the context of another object is not uncommon. The monitoring tool Godm for instance, uses it.

Repellent answered 11/7, 2009 at 12:24 Comment(1)
Where has this been suggested?Gamber
A
0

The nested lexical scope example that someone gave gives several benefits.

  1. "Safer" globals
  2. It is one method to embed DSL's into your program.

I think that is a very good example of the differences between the two languages. Ruby is simply more flexible. Python can be flexible, but you often have to do extreme contortions to get there, which makes it not worth the hassle.

Sorry for not posting under the original answer, I guess I don't have privileges to do that.

Apparatus answered 11/7, 2009 at 12:24 Comment(0)
M
-2

I am surprised that no one has mentioned Singleton methods.

a=[]
b=[]
def b.some_method do ... end
b.some_method #fine
a.some_method #raises exception

It gives granular control over the open class concept. You can also use Eigenclasses to mixin a module into a specific object instead of all objects of a given class.

o=Object.new
class << o
  include SomeModule
end

Python also doesn't have a switch statement without using ugly hacks which can decrease code readability.

Ruby has no statements,only expressions. This add a lot of flexibility.

You can get a reference to any method and pass that around.

a=[]
m=a.method :map #m is now referencing an instance of Method and can be passed like any other reference to an object and is invoked with the call method and an optional block

Easy nested lexical scope giving controlled global variables.

lambda {
   global=nil
   def Kernel.some_global= val
      global||=val
   end

  def Kernel.some_global
     global
  end
}.call

Once that lambda is invoked, global is out of scope, but you can set it(only once in this example) and then access it anywhere in your program. Hopefully the value of this is clear.

Creating a DSL is much easier in Ruby than in Python. Creating something like Rake or RSpec in Python is possible but what a nightmare it would be. So to answer your question Ruby has much more flexibility than Python. It is not at the flexibility level of Lisp, but is arguably the most flexible OO language.

Python is great and all but it is so stiff compared to Ruby. Ruby is less verbose, more readable(as in it reads much closer to a natural language), python reads like english translated to french.

Python is also annoying in that its community is always in lock-step with Guido, if Guido says that you don't need feature X, everyone in the community believes it and parrots it. It leads to a stale community, kind of like the Java community that simply can't understand what anonymous functions and closures buy you. The Python community is not as annoying as Haskell's, but still.

Makedamakefast answered 11/7, 2009 at 12:24 Comment(2)
"You can get a reference to any method and pass that around." has always been true for python. And the thing you call Singleton methods, too. As for annoying communities, well.....Alveolus
Noone mentioned singleton methods because you can do exactly the same thing in Python, so there is no difference. No, the value of what you call "easy nested lexical scope" compared to what you do in Python is not obvious. In fact, the only correct thing I can see in your answer above is that Python indeed do not have a switch statement. I'm not convinced using "elif"s is any less readable, though, but that's a matter of opinion, of course. With regards to the community, you are dead wrong.Gamber
H
-3

Ruby gets inheritance right with Single Inheritance

Did I mention Ruby has an EPIC community of developers. Ninja theme inspired by Object Oriented Ruby: Classes, Mixins and Jedi.

Ruby gets inheritance right with Single Inheritance! Needing to use multiple inheritance to express domain relationships is a symptom of an improperly designed system. The confusion multiple inheritance creates isn't worth the added functionality.

Say you have a method called kick:

def kick
  puts "kick executed."
end

What if kick is defined in both class Ninjutsu and class Shaolin? Multiple Inheritance fails here and that's why Python fails:

class Mortal < Ninjutsu, Shaolin
  def initialize
    puts "mortal pwnage."
  end
end

In Ruby if you need a Ninja, you create an instance of the Ninja class. If you need a Shaolin master, you create an instance of the Shaolin class.

ninja = Ninjutsu.new
ninja.kick

or 

master = Shaolin.new
master.kick

Ruby gets inheritance right with Mixins

There might be the off chance that both a Ninja and a Shaolin master share the same kick technique. Read that again - both share the same behavior - nothing else! Python would encourage you to roll a whole new class. Not with Ruby! In Ruby you simply use a Mixin:

module Katas
  def kick
    puts "Temporal Whip Kick."
  end
end

and simply Mixin the Katas module into your Ruby Class:

require 'Katas'

class Moral < Ninjutsu
  include Katas

  def initialize
    puts "mortal pwnage."
  end
end

Then the behavior gets shared - which is what you were really going for. Not an entire class. That's the biggest difference between Ruby and Python - Ruby gets inheritance right!

Humorous answered 11/7, 2009 at 12:24 Comment(2)
This is in no way the biggest difference; I'm sure people rarely use MI in Python at any rate. I'd be more inclined to look at open classes, metaclasses all the way down, blocks, freer syntax ...Lure
"Multiple Inheritance fails here" No it doesn't. "The confusion multiple inheritance creates isn't worth the added functionality." I've worked with Zope and Plone for ten years, it uses loads of Multiple inheritance, and there has never once been any confusion. "In Ruby you simply use a Mixin:" And how is that different from using a mixin class? Oh, right, it isn't. So the difference is that Python has multiple inheritance and Ruby hasn't. Framing it as Ruby gets it right goes from stating a difference to silly religious wars.Gamber
K
-4

While the functionalty is to a great extent the same (especially in the Turing sense), malicious tongues claim that Ruby was created for Pythonistas that could not split up with the Perlish coding style.

Kaisership answered 11/7, 2009 at 13:56 Comment(1)
Actually, it was created for Smalltalkers that want to break out of the image.Predominate

© 2022 - 2024 — McMap. All rights reserved.