有很多关于Python和Ruby的讨论,我都发现它们完全没有帮助,因为它们都围绕着为什么X特性在Y语言中很糟糕,或者声称Y语言没有X,尽管事实上它有。我也确切地知道为什么我更喜欢Python,但这也是主观的,对任何人的选择都没有帮助,因为他们可能与我在开发方面的品味不同。

因此,客观地列出这些差异将是有趣的。所以没有“Python的lambdas很糟糕”。相反,解释Ruby的lambda能做而Python不能做的事情。没有主体性。示例代码很好!

请不要在一个答案上有几个不同之处。然后给你认为正确的选项投票,把你认为不正确的(或主观的)选项投下。此外,语法上的差异也不有趣。我们知道Python对缩进的处理就像Ruby对括号和结束的处理一样,@在Python中被称为self。

更新:现在这是一个社区维基,所以我们可以在这里添加大的区别。

Ruby在类主体中有一个类引用

在Ruby中,类主体中已经有了对类(self)的引用。在Python中,直到类构造完成之后才有对类的引用。

一个例子:

class Kaka
  puts self
end

self在本例中是类,这段代码将打印出“Kaka”。在Python中,无法打印类名或以其他方式从类定义体(在方法定义之外)访问类。

Ruby中所有的类都是可变的

这使您可以开发核心类的扩展。下面是一个rails扩展的例子:

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

Python(想象没有”。startswith方法):

def starts_with(s, prefix):
    return s[:len(prefix)] == prefix

你可以在任何序列上使用它(不仅仅是字符串)。为了使用它,你应该显式地导入它,例如,从some_module import starts_with。

Ruby具有类似perl的脚本功能

Ruby拥有一流的regexp、$-variables、awk/perl逐行输入循环和其他特性,这些特性使它更适合编写小型shell脚本,这些脚本可以转换文本文件或充当其他程序的粘合代码。

Ruby具有一流的延续

多亏了callcc语句。在Python中,您可以通过各种技术创建continuation,但语言中没有内置的支持。

Ruby有块

通过“do”语句,您可以在Ruby中创建一个多行匿名函数,该函数将作为参数传递到do前面的方法中,并从那里调用。在Python中,您可以通过传递方法或使用生成器来完成此操作。

Ruby:

amethod { |here|
    many=lines+of+code
    goes(here)
}

Python (Ruby块对应于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

有趣的是,在Ruby中调用块的方便语句称为“yield”,在Python中它将创建一个生成器。

Ruby:

def themethod
    yield 5
end

themethod do |foo|
    puts foo
end

Python:

def themethod():
    yield 5

for foo in themethod():
    print foo

尽管原理不同,结果却惊人地相似。

Ruby更容易支持函数式(类管道)编程

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

Python:

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

Python有内置生成器(如上所述,像Ruby块一样使用)

Python支持该语言中的生成器。在Ruby 1.8中,您可以使用generator模块,该模块使用continuation从块中创建生成器。或者,你可以使用block/proc/lambda!此外,在Ruby 1.9中,光纤可以用作生成器,并且枚举器类是一个内置生成器4

Docs.python.org有这样一个生成器示例:

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

将其与上面的块示例进行对比。

Python具有灵活的名称空间处理

在Ruby中,当您使用require导入文件时,该文件中定义的所有内容都将在全局名称空间中结束。这会导致名称空间污染。解决方案就是ruby模块。但是如果使用模块创建名称空间,则必须使用该名称空间访问包含的类。

在Python中,该文件是一个模块,您可以从模块import *中导入其包含的名称,从而污染命名空间。但是你也可以从模块import aname中导入选定的名称,或者你可以简单地导入模块,然后使用module.aname访问这些名称。如果你想在你的命名空间中有更多的层,你可以有包,包是包含模块和__init__.py文件的目录。

Python有文档字符串

文档字符串是附加到模块、函数和方法的字符串 在运行时内省。这有助于创建帮助命令和 自动文档。

def frobnicate(bar):
    """frobnicate takes a bar and frobnicates it

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

Ruby的等效程序类似于javadocs,并且位于方法的上方而不是内部。它们可以在运行时使用1.9的Method#source_location示例从文件中检索

Python具有多重继承

Ruby没有(“故意的”——请参阅Ruby的网站,了解在Ruby中是如何做到的)。它将模块概念重用为一种抽象类。

Python有列表/字典推导式

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 Python

>>> {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有装饰器

在Ruby中也可以创建类似于装饰器的东西,也可以认为它们不像在Python中那样必要。

语法差异

Ruby需要“end”或“}”来关闭所有作用域,而Python只使用空白。Ruby中最近已经尝试允许只使用空格缩进http://github.com/michaeledgar/seamless


Ruby和Python中的类定义中都可以有代码。然而,在Ruby中,你有一个对类(self)的引用。在Python中,你没有对类的引用,因为类还没有定义。

一个例子:

class Kaka
  puts self
end

self在本例中是类,这段代码将打印出“Kaka”。在Python中,无法打印类名或以其他方式从类定义体访问类。


Ruby有块的概念,它本质上是围绕一段代码的语法糖;它们是一种创建闭包并将其传递给另一个方法的方法,该方法可能使用也可能不使用该块。稍后可以通过yield语句调用块。

例如,数组中each方法的简单定义可能是这样的:

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

然后你可以像这样调用它:

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

Python有匿名函数/闭包/lambdas,但它没有足够的块,因为它缺少一些有用的语法糖。但是,至少有一种方法可以以特别的方式获得它。比如,这里。


Python有文档字符串,ruby没有…如果没有,它们也不像在python中那样容易访问。

Ps.如果我错了,请留下一个例子?我有一个解决办法,我可以monkeypatch进入类很容易,但我想有文档字符串有点功能在“本机方式”。


Ruby相对于Python的优势在于它的脚本语言能力。脚本语言在此上下文中的意思是用于shell脚本和一般文本操作中的“粘合代码”。

这些主要与Perl共享。一流的内置正则表达式,$-Variables,有用的命令行选项,如Perl (-a, -e)等。

再加上它简洁而富有表现力的语法,它非常适合这类任务。

对我来说,Python更像是一种动态类型的业务语言,非常容易学习,而且语法简洁。没有Ruby那么“酷”,但是很简洁。 对我来说,Python相对于Ruby的优势是对其他库的大量绑定。绑定到Qt和其他GUI库,许多游戏支持库和和。Ruby拥有的要少得多。虽然很多常用的绑定(例如数据库绑定)质量都很好,但我发现Python中对利基库的支持更好,即使同一个库中也有Ruby绑定。

所以,我想说两种语言都有它的用途,是任务定义了使用哪一种。两者都很容易学。我把它们放在一起用。Ruby用于脚本,Python用于独立应用程序。


虽然功能在很大程度上是相同的(特别是在图灵的意义上),但恶意的语言声称Ruby是为python主义者创建的,不能与Perlish编码风格分离。


我不认为“Ruby有X而Python没有,而Python有Y而Ruby没有”是看待它最有用的方式。它们是非常相似的语言,有许多共同的能力。

在很大程度上,区别在于语言如何变得优雅和可读。以您提到的一个例子来说,两者理论上都有lambdas,但是Python程序员倾向于避免使用它们,并且使用它们构建的结构看起来不像Ruby中那样可读或惯用。所以在Python中,优秀的程序员会想要采用不同于Ruby的方法来解决问题,因为这实际上是更好的方法。


Python有一种“我们都是成年人”的心态。因此,您会发现Ruby有常量之类的东西,而Python没有(尽管Ruby的常量只会引发警告)。Python的思维方式是,如果你想让某些东西成为常数,你应该把变量名全大写,而不是改变它。

例如,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

Ruby有纹章和树枝,Python没有。

编辑:还有一件非常重要的事情我忘记了(毕竟,之前的只是燃烧一点点:-p):

Python有一个JIT编译器(Psyco),一种用于编写更快代码的低级语言(Pyrex),以及添加内联c++代码(Weave)的能力。


Ruby有内置的使用callcc的延续支持。

因此你可以实现一些很酷的东西,比如amb-operator


Python有一个显式的内置语法,用于列表理解和生成器,而在Ruby中,您将使用映射和代码块。

比较

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

to

res = (1..10).map{ |x| x*x }

我不确定这一点,所以我先把它作为一个答案。

Python将未绑定方法视为函数

这意味着你可以像调用object.themethod()一样调用方法,也可以通过class .themethod(anobject)调用方法。

编辑:尽管在Python中方法和函数之间的区别很小,并且在Python 3中不存在,但在Ruby中也不存在,因为Ruby没有函数。定义函数时,实际上是在Object上定义方法。

但是你仍然不能把一个类的方法作为一个函数来调用,你必须把它重新绑定到你想调用的对象上,这就更加困难了。


其他一些来自:

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

(如果我误解了任何东西,或者自该页更新以来Ruby端发生了任何变化,有人可以随意编辑…)

字符串在Ruby中是可变的,而在Python中不是(在Python中,新字符串是通过“更改”创建的)。

Ruby有一些强制的大小写约定,而Python没有。

Python有列表和元组(不可变列表)。Ruby有对应于Python列表的数组,但没有它们的不可变变体。

在Python中,可以直接访问对象属性。在Ruby中,总是通过方法。

在Ruby中,方法调用的圆括号通常是可选的,但在Python中不是。

Ruby具有公共、私有和受保护来强制访问,而不是像Python那样使用下划线和名称混淆。

Python具有多重继承。Ruby有“mixins”。

还有一个非常相关的链接:

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

特别是Alex Martelli的另一个很好的链接,他也在SO上发布了很多很棒的东西:

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


在Python中,只能从模块中导入特定的函数。在Ruby中,您导入整个方法列表。您可以在Ruby中“取消导入”它们,但这并不是它的全部内容。

编辑:

让我们看看这个Ruby模块:


module Whatever
  def method1
  end

  def method2
  end
end

如果你在代码中包含它:


include Whatever

您将看到method1和method2都已添加到您的名称空间。你不能只导入method1。要么同时导入它们,要么根本不导入。在Python中,只能导入自己选择的方法。如果要给它起个名字也许可以叫选择性导入?


Ruby从命令行开始逐行循环输入文件('-n'标志),因此它可以像AWK一样使用。这是Ruby的一行代码:

ruby -ne 'END {puts $.}'

将计数像AWK一行代码一样的行数:

awk 'END{print NR}'

Ruby通过Perl获得了这一特性,Perl从AWK中获得了这一特性,作为一种让系统管理员使用Perl的方式,而不必改变他们做事的方式。


Python示例

在Python中,函数是第一类变量。你可以声明一个函数,将它作为对象传递,然后覆盖它:

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

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

这是现代脚本语言的一个基本特性。JavaScript和Lua也可以做到这一点。Ruby不是这样对待函数的;命名一个函数调用它。

当然,在Ruby中有很多方法来做这些事情,但它们不是一流的操作。例如,你可以用Proc.new包装一个函数,把它当作一个变量——但这样它就不再是一个函数了;它是一个具有“call”方法的对象。

Ruby的函数不是一级对象

Ruby函数不是一级对象。函数必须包装在对象中才能传递;生成的对象不能像函数一样处理。不能以一流的方式分配函数;相反,必须调用容器对象中的函数来修改它们。

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!"    

Python已经命名了可选参数

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只有定位参数,因为函数声明中的b=2是一个总是附加的修饰。


“以大写字母开头的变量成为常数,不能修改”

错了。他们可以。

如果你这么做了,你只会得到警告。


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:

调用一个obj的__getattribute__方法 __getattribute__从类dict检索一个attr对象 它检查abAttr对象是否有__get__, __set__或__delete__可调用对象 上下文(即,调用者对象或类,如果我们有setter,值,而不是后者)被传递给可调用对象 返回结果。

如前所述,这是默认行为。可以通过重新实现__getattribute__来自由更改协议。

这种技术比装饰器强大得多。


惊讶地看到ruby没有提到“方法缺失”机制。我将给出find_by_…方法,作为该语言功能强大的一个例子。我的猜测是类似的东西可以在Python中实现,但据我所知,它并不是原生的。


Ruby有嵌入式文档:

 =begin

 You could use rdoc to generate man pages from this documentation

 =end

我的python已经生锈了,所以其中一些可能是在python中,我只是不记得/从未在第一个地方学习过,但这里是我想到的第几个:

空格

Ruby处理空白的方式完全不同。对于初学者来说,你不需要缩进任何东西(这意味着不管你是使用4个空格还是1个制表符)。它也做智能续线,所以下面是有效的:

def foo(bar,
        cow)

基本上,如果你以一个运算符结尾,它会找出发生了什么。

Mixins

Ruby有mixins,它可以扩展实例,而不是完整的类:

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

枚举

我不确定这是否与生成器相同,但Ruby 1.9的Ruby作为枚举,所以

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

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

“关键字参数”

Ruby支持上面列出的两项,尽管您不能跳过这样的默认值。 你可以按顺序去

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

注意,c=5实际上将调用范围内的变量c赋值为5,并将参数b设置为5。

或者你也可以用散列来解决第二个问题

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

参考:实用的Ruby程序员指南


我想提出一个原始问题的变体,“Ruby有哪些Python没有的,反之亦然?”这个问题承认了一个令人失望的答案,“好吧,你可以用Ruby或Python做哪些在Intercal中不能做的事情?”没有,因为Python和Ruby都是坐在图灵近似宝座上的庞大皇室家族的一部分。

但是这个呢:

在Python中可以优雅而出色地完成哪些在Ruby中无法以如此美丽和出色的工程完成的工作,反之亦然?

这可能比单纯的特征比较有趣得多。


来自Ruby的网站:

相似之处 和Python一样,在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).

差异 与Python不同,在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.


更多的是在基础设施方面:

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.


Python和Ruby之间lambdas的另一个区别是由Paul Graham的Accumulator Generator问题演示的。转载:

写一个函数foo,它接受一个数字n,并返回一个接受数字i的函数,返回n加i。 注意:(a)是数字,不是整数,(b)是加,不是加。

在Ruby中,你可以这样做:

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

在Python中,你可以创建一个对象来保存n的状态:

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

有些人可能更喜欢显式的Python方法,因为它在概念上更清晰,即使它有点啰嗦。你像储存其他东西一样储存状态。您只需要理解可调用对象的概念。但是不管人们在美学上更喜欢哪种方法,它确实显示了Ruby lambdas结构比Python更强大的一个方面。


http://c2.com/cgi/wiki?PythonVsRuby http://c2.com/cgi/wiki?SwitchedFromPythonToRuby http://c2.com/cgi/wiki?SwitchedFromRubyToPython http://c2.com/cgi/wiki?UsingPythonDontNeedRuby http://c2.com/cgi/wiki?UsingRubyDontNeedPython


Alex Martelli在comp.lang.python邮件列表中关于“Ruby比Python有什么更好”的回答。

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!): Ruby's iterators and codeblocks vs Python's iterators and generators; 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


在Ruby中,当你用 Require,定义的所有东西 该文件将在全局变量中结束 名称空间。

使用Cargo,你可以“在不弄乱名称空间的情况下要求库”。

# 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"

在这个阶段,Python仍然有更好的unicode支持


最终,所有的答案在某种程度上都是主观的,到目前为止发布的答案几乎证明了你不能以同样好的方式(如果不是相似的话)指出任何一个功能在另一种语言中是不可行的,因为这两种语言都非常简洁和富有表现力。

我喜欢Python的语法。但是,除了语法之外,您还必须深入挖掘Ruby的真正魅力。在林心如的一贯中有一种禅意般的美。虽然没有一个简单的例子可以完全解释这一点,但我会试着在这里举一个例子来解释我的意思。

颠倒这个字符串中的单词:

sentence = "backwards is sentence This"

当你考虑如何做到这一点时,你会这样做:

把这个句子分成几个单词 颠倒单词 将单词重新连接成字符串

在Ruby中,你可以这样做:

sentence.split.reverse.join ' '

正如您所想的那样,在相同的顺序中,一个方法调用另一个方法。

在python中,它看起来更像这样:

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

这并不难理解,但它并没有完全相同的流程。主语(句)被埋没在中间。操作是函数和对象方法的混合。这是一个简单的例子,但是当你真正使用和理解Ruby时,你会发现许多不同的例子,特别是在非简单的任务中。


我喜欢Ruby和Python方法调用操作方式的根本区别。

Ruby方法是通过表单“消息传递”调用的,不需要显式地是第一类函数(有一些方法可以将方法提升为“适当的”函数对象)——在这方面,Ruby类似于Smalltalk。

Python的工作原理更像JavaScript(甚至Perl),其中方法是直接调用的函数(也存储了上下文信息,但是……)

虽然这看起来像是一个“小”细节,但它实际上只是Ruby和Python设计差异的表面。(另一方面,它们也是一样的:-)

一个实际的区别是Ruby中的method_missing概念(不管怎样,它似乎在一些流行的框架中使用)。在Python中,可以(至少部分地)使用__getattr__/__getattribute__来模拟这种行为,尽管不是惯用方法。


Ruby通过单继承获得了正确的继承

我提到过Ruby有一个EPIC的开发者社区吗?忍者主题灵感来自面向对象的Ruby:类,Mixins和绝地武士。

Ruby通过单继承获得了继承权!需要使用多重继承来表示域关系是设计不当的系统的一个症状。多重继承造成的混乱不值得增加功能。

假设你有一个叫kick的方法:

def kick
  puts "kick executed."
end

如果“踢”在忍术和少林中都有定义呢?多重继承在这里失败了,这就是Python失败的原因:

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

在Ruby中,如果你需要一个Ninja,你可以创建一个Ninja类的实例。如果需要一个少林大师,可以创建一个少林类的实例。

ninja = Ninjutsu.new
ninja.kick

or 

master = Shaolin.new
master.kick

Ruby通过Mixins获得了正确的继承

也许忍者和少林大师有一种相同的踢法。再读一遍——两者都有相同的行为——没有别的!Python会鼓励您滚动一个全新的类。不是和鲁比!在Ruby中,你只需使用Mixin:

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

简单地将Katas模块混合到Ruby类中:

require 'Katas'

class Moral < Ninjutsu
  include Katas

  def initialize
    puts "mortal pwnage."
  end
end

然后这种行为就被分享了——这才是你真正想要的。不是整个班级。这是Ruby和Python之间最大的区别——Ruby获得了正确的继承!


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.

标准符号使我们所讨论的数字一目了然,但计算它们的顺序却不明确。前缀和后缀表示法使计算顺序清晰明了,同时使数字模糊。如果不是语法空白造成的困难,Python已经有了多行lambda。(确实存在这样的建议,即不需要添加显式的块分隔符。)

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.

肤浅的是我们归于语法的美的审美品质。美学与我们的认知如何运作无关,但句法起作用。


我很惊讶没有人提到Singleton方法。

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

它提供了对开放类概念的粒度控制。您还可以使用Eigenclasses将一个模块混合到一个特定的对象中,而不是给定类的所有对象中。

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

Python也没有一个switch语句,而不使用丑陋的hack,这会降低代码的可读性。

Ruby没有语句,只有表达式。这增加了很大的灵活性。

您可以获得任何方法的引用并传递它。

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

易于嵌套的词法范围,提供受控制的全局变量。

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

  def Kernel.some_global
     global
  end
}.call

一旦该lambda被调用,global就超出了作用域,但是您可以设置它(在本例中只有一次),然后在程序中的任何地方访问它。希望这个的价值很清楚。

在Ruby中创建DSL要比在Python中容易得多。用Python创建Rake或RSpec之类的东西是可能的,但这将是一场噩梦。所以回答你的问题,Ruby比Python有更多的灵活性。它没有达到Lisp的灵活性级别,但可以说是最灵活的OO语言。

Python很棒,但与Ruby相比,它太死板了。Ruby不那么啰嗦,可读性更强(因为它读起来更接近自然语言),python读起来像英语翻译成法语。

Python的另一个恼人之处在于它的社区总是与Guido步调一致,如果Guido说你不需要X特性,社区里的每个人都相信它并鹦鹉学舌。它导致了一个陈旧的社区,有点像Java社区,根本无法理解匿名函数和闭包能给您带来什么。Python社区不像Haskell社区那样令人讨厌,但仍然如此。


某人给出的嵌套词法范围示例有几个好处。

“更安全”的全局变量 这是将DSL嵌入到程序中的一种方法。

我认为这是两种语言之间差异的一个很好的例子。Ruby更加灵活。Python可以很灵活,但通常必须做一些极端的扭曲才能达到这一点,这使得它不值得麻烦。

抱歉没有在原来的答案下面发帖,我想我没有权限这么做。


更多关于Ruby的积木

有人建议Ruby的块可以被Python的上下文管理器“取代”。事实上,块所允许的功能比Python的上下文管理器所能做到的还要多。

块的接收方法可以在某个对象的上下文中执行该块,从而允许块调用其他情况下无法到达的方法。Python的生成器也不能做到这一点。

一个简单的例子可能会有所帮助:

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 }

在这个例子中,块{hello}中的方法调用在目标对象c的上下文中具有真实的意义。

此示例仅用于说明目的。在另一个对象的上下文中使用这种执行的实际工作代码并不少见。例如,监控工具Godm就使用它。