为什么Ruby比Python更适合Rails?

92

Python和Ruby通常被认为是密切相关的表亲(尽管它们有着相当不同的历史背景),具有类似的表达力和能力。但是一些人认为,Rails框架的巨大成功确实与它所建立在的语言:Ruby本身有很大关系。那么为什么Ruby比Python更适合这样的框架呢?


45
头韵。 - Jimmy
75
“Python on Pails”这个名称就是感觉不一样… - ephemient
105
我认为这将是“Python在飞机上”。 - Jimmy
37
@Jimmy:谁需要飞机?导入antigravity ;-) http://xkcd.com/353/ - Vinay Sajip
157
监狱中是否有Java? - Nosredna
显示剩余13条评论
13个回答

172

可能存在两个主要区别:

Ruby拥有优雅的匿名闭包。

Rails 很好地运用了它们。以下是一个例子:

class WeblogController < ActionController::Base
  def index
    @posts = Post.find :all
    respond_to do |format|
      format.html
      format.xml { render :xml => @posts.to_xml }
      format.rss { render :action => "feed.rxml" }
    end
  end
end

使用匿名闭包/lambda函数可以更轻松地模拟需要块的新语言特性。在Python中,闭包存在,但必须命名后才能使用。因此,无法像使用闭包来模拟新的语言特性一样,你被迫明确表示正在使用闭包。

Ruby具有更清晰、更易于使用的元编程功能。

这在Rails中被广泛使用,主要是因为其易用性。具体而言,在Ruby中,可以在类的上下文中执行任意代码。以下代码片段是等价的:

class Foo
  def self.make_hello_method
    class_eval do
      def hello
        puts "HELLO"
      end
    end
  end
end

class Bar < Foo # snippet 1
  make_hello_method
end

class Bar < Foo; end # snippet 2
Bar.make_hello_method

在这两种情况下,你都可以执行以下操作:

Bar.new.hello  

这段代码将打印出"HELLO"。方法class_eval可以接受一个字符串参数,因此在创建类的同时,可以动态创建具有不同语义的方法,取决于所传递的参数。

实际上,在Python(以及其他一些语言)中也可以进行这种元编程,但Ruby更加先进,因为元编程不是一种特殊的编程风格,而是从Ruby的对象模型和代码执行机制中自然流露出来的。因此,Class本身也是一个对象,类体具有指向该类的self,您可以在创建类时对类调用方法。

这在很大程度上解释了Rails中可实现声明性编程的程度,以及我们能够轻松实现新的声明性特性,看起来像关键字或新的块语言特性。


40
在Python中,一切皆为对象,所有代码行也直接执行。但是,在类定义体中没有指向类的"self",只有在类定义之后才会创建它,因此在Python中,您必须将该代码放在类定义之后。虽然这种做法可能不太优美,但其实现效果相同。 - Lennart Regebro
32
@lennart 这正是重点。Python 允许您使用命名的 lambda、装饰器以及在类创建之后放置代码来完成相同类型的事情,但是优雅度的损失会迅速累积,并使得像 Rails 这样的东西要么实现起来明显更难,要么对最终用户来说不够优雅。 - Yehuda Katz
9
我觉得它们并不像重大的差异。 - Dietrich Epp
10
@lennart,我有点困惑。我的意思是在Python中你不需要它们——但是如果没有它们,代码会更难实现或对最终用户来说不够优雅(二选一)。这些语言都是图灵完备的——你可以用C写Rails。 - Yehuda Katz
5
现在我们进入了主观领域,但我所说的两个特点在制作混合声明式和过程式编程框架时非常方便。特别是匿名lambda函数的缺失,是Python表达能力的限制。同样,缺乏一致性(只能在类创建之后使用创建的类)也相当有限制性。 - Yehuda Katz
显示剩余17条评论

58

认为Rails框架的巨大成功与其所依赖的语言有很大关系的人是错误的(IMO)。这种成功可能更多地归功于聪明而持久的市场营销,而不是任何技术上的造诣。Django 在许多领域(例如内置的强大管理员)可能做得更好,而无需使用Ruby的任何特性。我并不是在贬低Ruby,只是在支持Python!


10
好的,我们正在进入主观领域。如果您认为管理员是“唯一”的,那么可能是因为您没有享受其节省时间的好处。您认为Django中是否有任何区域比Rails做得更差,因为Ruby具有而Python没有的功能?重点实际上不在于哪个框架更好-而是是否(如本问题的其他地方所指出)有任何缺乏Python使其无法开发强大的框架。根据证据,没有这样的缺乏。 - Vinay Sajip
18
对于那些给我点踩的人:我并不在意,但我很好奇你们认为我的回答为什么“无助”。我以前不知道点踩是因为对某个人立场持不同意见而进行的,通常情况下我只会在我认为某个问题或答案会使情况恶化时才会点踩。 - Vinay Sajip
5
我可以自己编写管理后台,不需要在框架中使用。我更喜欢其他方式来使我的应用程序更容易编写。 - nitecoder
8
@railsninja:恭喜你。我不喜欢为大多数系统需要的管理杂务编写样板页面。最近,我为一家本地慈善网站做了一些义务工作,如果Django管理界面不是其中的一部分,就根本无法完成该网站。最终,我提供了一个对终端用户进行了相当定制化的Ajax界面的站点,但后端管理员使用了管理界面,这已经足够满足他们的需求了。 - Vinay Sajip
6
@Matt:他的问题是为什么Ruby比Python更适合...而回答是,确切地说,并非如此。 - Lennart Regebro
显示剩余12条评论

54

Python社区认为以最简单和直接的方式完成事情是最高的优雅形式。Ruby社区认为以允许编写酷代码的巧妙方式完成事情是最高的优雅形式。

Rails完全基于约定,如果您遵循某些约定,许多其他事情将神奇地发生在您身上。这非常符合Ruby看待世界的方式,但并不完全遵循Python的方式。


4
好的,但是有许多 Perl 人(也许不是“很多”)认为晦涩难懂的一行代码很酷,而许多 Lisp 人则坚信它是唯一正确的编程语言。我们肯定处于“各有所好”的领域。 - Vinay Sajip
4
Rails没有任何魔法,它就在源代码里。如果你想知道如何实现,那就起身去找答案吧。 - nitecoder
21
“任何足够先进的科技都无法与魔法区分开来。”-亚瑟·克拉克(Arthur C. Clarke) - Vinay Sajip
1
“Magic” 意味着框架会在没有直接要求的情况下为您完成许多事情。再次声明,我不做价值判断,这是一种有好有坏的编程风格。就个人而言,我认为 Rails 中的这种方式非常有效。 - Matt Briggs
2
优雅和规范并不代表有魔法。 - BJ Clark
显示剩余7条评论

26

就我个人而言,我认为Ruby在很多方面都比Python更加优越,这些方面构成了我所谓的“一致表达能力”。例如,在Ruby中,join是数组对象上的一个方法,可以输出一个字符串,因此你会得到类似于下面的东西:

numlist = [1,2,3,4]
#=> [1, 2, 3, 4]
numlist.join(',')
#=> "1,2,3,4"
在Python中,join是字符串对象的一个方法,但如果您传递给它一个非字符串的对象作为要连接的东西,它会引发错误。因此,相同的结构可以改为:
numlist = [1,2,3,4]
numlist
#=> [1, 2, 3, 4]
",".join([str(i) for i in numlist])
#=> '1,2,3,4'

有很多这些小差异,随着时间的推移会逐渐积累。

而且,我想不出比使空格变得重要更好的方法来引入隐藏的逻辑错误了。


29
我的经验是,使空格成为重要标志可以帮助消除逻辑错误。如果空格和语法不一致,会更加令人困惑。 - Nosredna
5
在使用有开始和结束符号的语言、花括号语言以及汇编语言时,我曾经看到过错误复制代码并且在后面造成麻烦的情况。这总是一个问题。你是否遇到过很多人粘贴不好 Python 代码导致问题? - Nosredna
5
Python 中空格不重要:http://www.secnetix.de/~olli/Python/block_indentation.hawk。在 Python 中,由于缩进而导致“隐形错误”几乎是不可能的(你必须篡改编辑器设置),而在任何其他语言中,都完全有可能因为缩进不当而引入隐形错误。@fields: 所以不要通过 Skype 或 HTML 复制代码。天哪。 - Lennart Regebro
7
如果你尝试将非字符串类型添加到字符串中,例如在Join操作中,Python会报错。这是因为显式优于隐式。Python中很少进行自动转换,原因是这往往会导致问题,特别是在动态语言中,因为最终类型可能与预期不符。虽然在一开始使用 "".join() 方法可能有些反直觉,但实际上这就是原因。在列表中使用该方法实际上是没有意义的。 - Lennart Regebro
8
全能的上帝...你的意思是静态类型而不是强类型。Python 是强类型语言,Ruby 也是。 https://dev59.com/2HRB5IYBdhLWcg3wxZ1K在 Ruby 中也不能将字符串和整数相加。我已经厌倦了纠正你,请在回答之前检查你的事实。 - Lennart Regebro
显示剩余13条评论

26

这场辩论是新的“vim vs emacs”辩论吗?

我是Python / Django程序员,到目前为止,我还没有发现该语言/框架存在导致我转向Ruby / Rails的问题。

我可以想象如果我有Ruby / Rails的经验,情况也会是一样的。

两者都有类似的哲学,并以快速优雅的方式完成工作。更好的选择是你已经知道的。


15

PythonRuby都不是更好/更差的web框架候选者。如果想要客观性,您需要在两种语言中编写一些代码,然后查看哪种最符合您的个人偏好,包括社区。

大多数辩论其中一种语言的人要么从未认真使用过另一种语言,要么是为他们个人偏好“投票”。

我猜想大多数人定居于首先接触到的内容,因为它教给他们一些新东西(MVC,测试,生成器等)或做得更好(插件,模板等)。我曾经用PHP开发,并与RubyOnRails接触过。如果我在发现Rails之前知道了MVC,我很可能永远不会放弃PHP。但是,一旦我开始使用Ruby,我就喜欢语法、功能等等。

如果我首先发现Python及其MVC框架,我很可能会赞扬那种语言!


11

Python有许多类Rails的框架。它们的数量非常之多,以至于一个笑话是在PyCon上的典型演讲中,至少会谈到一个Web框架。

我认为Ruby的元编程能力更适合这种情况的观点是不正确的。对于这样的框架,您不需要元编程技巧。

因此,我认为可以得出结论:在这方面,Ruby并不比Python更好(也很可能不会更差)。


8
因为Rails是为了利用Ruby的特性而开发的。
类似地,一个毫无头脑的问题是“为什么Python比Ruby更适合Django?”。

4

我认为我们不应该讨论语言特性本身,而是应该关注各个社区对语言特性的重点。例如,在Python中,重新打开一个类是完全可能的,但并不常见;然而在Ruby中,重新打开一个类是日常实践的一部分。这使得框架能够快速简单地定制到当前需求,并使得Ruby比其他动态语言更适合于类似Rails的框架。

因此我的答案是:重新打开类的常见使用。


1

有人说,为了使ActiveRecord(Rails的关键组件)成为可能所需的元编程类型在Ruby中比Python更容易且更自然 - 我还不会Python;),因此我无法亲自确认这个说法。

我曾经简要使用过Rails,它使用的catchalls/拦截器和动态评估/代码注入确实允许您在比其他框架(在其时代之前)更高的抽象级别上操作。我对Python的框架几乎没有任何经验 - 但我听说它同样具备能力 - 并且Python社区在支持和培育Pythonic事业方面做得非常出色。


3
实际上,在 Python 中这种“魔法”常常会受到贬低;例如,http://code.djangoproject.com/wiki/RemovingTheMagic。 - ephemient
2
我认为仅仅为了“魔法”而使用元编程技巧应该被反对——简单的代码同样可以强大而富有表现力,它们应该始终胜出——但是在某些情况下,为了提供您想要的确切功能和语法,唯一的方法就是使用“魔法”——在这些情况下,“魔法”是不可或缺的 ;) - Faisal Vali

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接