Ruby有什么Python没有的,反之亦然?

有很多关于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

你可以在任何序列上使用它(不仅仅是字符串)。为了使用它,你应该导入它显式地,例如,from 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)

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

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

Python有文档字符串

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

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的方法#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 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有装饰器

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

语法差异

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

134859 次浏览

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

一个例子:

class Kaka
puts self
end

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

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

例如,each方法在Array上的简单定义可能是这样的:

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),一个美观的低级语言,用于编写更快的代码(派热克斯玻璃),并能够添加内联c++代码()。

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

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

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

比较

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

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

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

Python将未绑定方法视为函数

这意味着你可以调用类似theobject.themethod()TheClass.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

特别是亚历克斯·马尔泰利的另一个好作品的链接,他也在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

你会看到method1method2都被添加到你的命名空间中。你不能只导入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是一个总是附加的修饰。

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

错了。他们可以。

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

我想提一下Python描述符API,它允许一个自定义对象到属性的“通信”。同样值得注意的是,在Python中,可以通过覆盖__getattribute__方法的默认实现来自由实现替代协议。 我再详细说明一下。 描述符是具有__get____set__和/或__delete__方法的常规类。 当解释器遇到类似anObj.anAttr的情况时,执行以下操作:

  • 调用anObj__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)

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

mixin

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的网站:

< p >相似之处 与Python一样,在Ruby中,…

  • 有一个交互式提示符(称为irb)。
  • 您可以在命令行上读取文档(使用ri命令而不是pydoc)。
  • 没有特殊的行结束符(除了通常的换行符)。
  • 字符串字面值可以跨越多行,比如Python的三引号字符串。
  • 括号用于列表,大括号用于字典(在Ruby中称为“散列”)。
  • 数组的工作原理是一样的(添加它们会形成一个长数组,但像这样组合它们a3 = [ a1, a2 ]会给你一个数组的数组)。
  • 对象是强类型和动态类型的。
  • 所有东西都是对象,变量只是对象的引用。
  • 尽管关键字略有不同,但异常的工作原理基本相同。
  • 你有嵌入式文档工具(Ruby的称为rdoc)。
< p >差异 与Python不同,在Ruby中,…

  • 字符串是可变的。
  • 你可以创建常量(你不打算改变其值的变量)。
  • 有一些强制的大小写约定(例如类名以大写字母开头,变量以小写字母开头)。
  • 列表容器只有一种(数组),它是可变的。
  • 双引号字符串允许转义序列(如\t)和特殊的“表达式替换”语法(允许您直接将Ruby表达式的结果插入到其他字符串中,而不必“添加”+“字符串”+“一起”)。单引号字符串就像Python的r“原始字符串”。
  • 没有“新风格”和“旧风格”类。只有一种。
  • 您永远不会直接访问属性。在Ruby中,所有的都是方法调用。
  • 方法调用的括号通常是可选的。
  • 有public, private和protected来强制访问,而不是Python的_voluntary_ underscore __convention__
  • " mixin 's "被用来代替多重继承。
  • 您可以添加或修改内置类的方法。这两种语言都允许您在任何时候打开和修改类,但是Python阻止修改内置类—Ruby则不会。
  • 你得到了true和false而不是true和false (nil而不是None)。
  • 当测试真值时,只有false和nil计算为假值。其他所有内容都为真(包括0、0.0、""和[])。
  • 它是elsif而不是elif。
  • 它是require而不是import。除此之外,用法是一样的。
  • 在东西上面的行(而不是在它们下面的文档字符串)上的常规风格注释用于生成文档。
  • 有很多捷径,虽然让你记住更多,但你很快就能学会。它们使Ruby变得有趣且高效。

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

  • Python与c++有更好的集成(通过Boost。PythonSIP,和Py++)而不是Ruby,其中的选项似乎要么是直接写对Ruby解释器API(当然,你也可以用Python,但在这两种情况下,这样做是低级的,繁琐的,容易出错)或使用SWIG(其中,虽然如果你想支持多种语言,它肯定是很棒的,但它远不如Boost好。Python或SIP(如果您特别希望绑定c++)。

  • Python有许多web应用程序环境(Django, Pylons/Turbogears, web.py,可能至少有半打其他),而Ruby(实际上)只有一个:Rails。(其他Ruby web框架确实存在,但似乎很难与Rails相比)。这方面是好还是坏?很难说,而且可能相当主观;我可以很容易地想象到这样的争论:Python的情况更好,Ruby的情况更好。

  • 在文化上,Python和Ruby社区似乎有些不同,但我只能暗示这一点,因为我没有太多与Ruby社区交互的经验。我补充这一点主要是希望那些在这两方面都有丰富经验的人可以放大(或拒绝)这一说法。

Python和Ruby之间lambdas的另一个区别是由Paul Graham的蓄电池发电机问题演示的。转载:

写一个函数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更强大的一个方面。

无耻地复制/粘贴从:Alex Martelli回答" Ruby比Python更好的是什么"线程从comp.lang. Python。Python 邮件列表。

Aug 18 2003,上午10:50 Erik Max Francis 写道:< / p >

“Brandon J. Van Every”写道:

Ruby比Python有什么优点?我相信一定有什么。 是什么?< / p >
问Ruby的人这个问题不是更有意义吗,而不是 Python的人?< / p >

可能,也可能不,取决于 一个人的目的——例如,如果 一个人的目的包括“社会学的” Python社区的“研究” 向社区提出问题是 很可能证明更多的揭示 信息关于它,比放 其他:-)。< / p > 就我个人而言,我很乐意接受 有机会跟随戴夫·托马斯 在最后的OSCON上有一天的Ruby教程。 在语法的薄板之下 不同之处,我发现Ruby和Python 惊人的相似——如果我是的话 计算最小生成树 在几乎所有的语言中, 我很确定Python和Ruby会的 成为最先结合的两片叶子 进入中间节点:-).

当然,在Ruby中,我确实厌倦了 在末尾输入愚蠢的“结束” 每个区块(而不是仅仅 )——但后来我确实得到了 避免输入同样愚蠢的':' Python在 开始的每个块,所以这几乎是一个洗:-)。其他的语法 例如“@foo”和 的自我。Foo ',或者更高的意义 Ruby和Python的区别

其他人无疑基于他们的选择 编程语言就是这样 问题,它们会产生最热门的 辩论,但对我来说那只是 帕金森定律的一个例子 行动(关于辩论的数额) 问题与问题成反比 问题的实际重要性)

编辑 (by AM 6/19/2010 11:45):这也被称为“painting the “Bikeshed”(简称Bikeshed) “bikeshedding”)——这里指的是, 再次感谢诺斯科特·帕金森,他 就该画什么颜色进行“辩论” 作为一个典型的例子 “关于琐碎话题的激烈辩论”。 (end-of-Edit)。< / p > 我确实发现了一个语法差异 重要,而且对Python有利—— 但其他人无疑会认为 正好相反——就是“how do you。 调用一个参数为no的函数 参数”。在Python中(就像在C中一样), 要调用一个函数,你总是应用 “调用操作符”—尾随 在对象后面加括号 你调用(在那些尾随的 括号是你传递的参数 在电话里,如果你拒绝的话 Args,那么括号是空的)。 这就只剩下 任何对象,不涉及操作符,表示只是引用 对于对象,在任何情况下, 没有特殊情况,例外, 特殊规则,诸如此类。在Ruby中 (如在Pascal中),来调用函数 使用参数传递参数 (通常在括号中,尽管 并非总是如此)——但是如果 这个函数不带参数 隐式地提到函数 调用它。这可能会满足 许多人的期望(至少, 毫无疑问,那些只属于以前的人 有编程经验 Pascal,或其他语言 类似的“隐性召唤”,比如 Visual Basic),但对我来说,它意味着 只要提到一个物体就可能 要么表示对对象的引用, 或对对象的调用,取决于 对象的类型 我找不到参考资料的案子 我仅仅提到它,就把它当作一个对象 将需要使用明确的“give me a ? 提到这个,不要这么说!” 不需要的运算符 否则。我觉得这会影响 函数的“一级性”(或 方法,或其他可调用对象) 以及交换的可能性 对象顺利。因此,对我来说, 这个特定的语法差异是 严重的污点对Ruby——但是 我能理解为什么别人会这么想 否则,即使我几乎不能 更强烈地反对他们:-).

在语法下面,我们进入一些 初级阶段的重要区别 语义——例如,字符串 Ruby是可变对象(比如in c++),而在Python中则不是 可变的(就像在Java中,或者我相信 c#)。还是那些爱评头论足的人 主要是他们已经拥有的东西 熟悉可能会认为这是一个加分项 Ruby(除非他们熟悉 Java或c#,当然:-)。我想 不可变字符串是一个很好的选择 (我并不惊讶Java, 独立地重新发明了它 这个想法已经在Python中了), 虽然我不介意有一个 "可变字符串缓冲区"类型 (最好是一个更好的 比Java自己的“字符串”更易于使用 缓冲区”);我不给你这个 因为熟悉而做出判断—— 在学习Java之前,除了 函数式编程语言 所有数据是不可变的,我知道的所有语言都有可变的字符串 ——然而,当我第一次在Java中看到不可变字符串的思想时 在我学习Python之前,我已经学得很好了), 它立刻让我觉得非常棒, 非常适合 更高层次的引用语义 编程语言(相对于 最适合的值-语义 语言更接近机器和 C选项是正确答案。 弦是一流的, 内置(非常重要的)数据 类型。< / p > Ruby确实有一些优势 基本语义——例如, 删除Python的“lists vs . list” 元组“极其微妙 的区别。但最主要的是分数(如 我保留了它,简单是一个很大的优点 和微妙的,聪明的区别 值得注意的缺点)不利于Ruby(例如, 既封闭又半开放的 用a..b和 一个……B .任何人都想这么说 它是明显的哪个是哪个?-)],是 愚蠢——当然!)再一次, 那些考虑拥有很多的人 相似但又有细微差别的东西 语言的核心是一个加分项 而不是负,当然也算 这些“反其道而行之” 我数了一下:-).

不要被这些比较所误导 认为这两种语言是 非常不同,注意。他们不是。但如果让我比较 "capelli d'angelo"到"spaghetti " 在指出这两个之后 意大利面的种类差不多 任何人都无法分辨 可以用在任何菜里 想要准备,我会那时 不可避免地要搬进去 显微检查如何 长度和直径难以察觉 不同的是,线的末端如何 是锥形的在一个案件,而不是在 其他的,等等,试着解释 为什么我个人更愿意呢 就像意大利面食一样 有点像肉汤,但我更喜欢 意面是外带的意面 配上合适的酱汁 薄面食(橄榄油,切碎 大蒜,红辣椒末,切碎 比如磨碎的凤尾鱼,但如果 你把大蒜和辣椒切成片 而不是对他们耍花招,然后是你 应该选择身体更健康的吗 意大利面而不是更薄的 意面的消逝,会 明智的建议是放弃抵押贷款 取而代之的是一些新鲜的春天 巴兹尔[甚至——我是个异教徒……!]-- 光薄荷……叶子——在非常 上菜前的最后一刻)。 不好意思,这说明我 出国旅游还没吃过意大利面 我想是暂时的吧。但是这个类比 仍然很不错!-)

那么,回到Python和Ruby,我们来 这两个大的(在 语言得体——离开 图书馆和其他重要的东西 辅助工具等 环境,如何嵌入/扩展每个环境 语言,等等,等等,暂时别想了 ——它们不会适用于每种语言的所有实现 无论如何,例如Jython vs Classic Python 的两个实现 Python语言!):< / p >
  1. Ruby的迭代器和代码块vs Python的迭代器和生成器;

  2. Ruby的TOTAL,肆无忌惮的“动态”,包括能力
    要“重新打开”任何现有的类, 包括所有内置的,和 在运行时更改其行为——vs Python是巨大的,但是有界的 动态性,永远不会改变 现有内置的行为

就我个人而言,我认为1是一种洗 差异如此之大,以至于我可以 很容易看出人们讨厌这两种 接近并尊敬对方,但是 就我个人而言,这些优点和优点 减去几乎相等);和2 a 关键问题,让Ruby 更适合“修补”, 但是Python同样更适合 用于大型生产应用。 在某种程度上,这很有趣,因为两者都是 语言是如此的动态 比其他大多数人,那最后 他们之间的关键区别 POV应该取决于Ruby 在这方面,“到十一”(the 这里提到的是"脊椎穿刺 课程)。在Ruby中,没有限制 对我的创造力——如果我决定的话 所有字符串比较必须为 不区分大小写,我可以这么做 ! 也就是说,我可以动态地改变 内置的字符串类 a = "Hello World" B = "hello world" 如果a == b 打印“平等!\ n” 其他的 打印”不同!\ n” 结束将打印“相等”。在python中,我无法做到这一点。 为了实现元编程, 实施实验性框架, 诸如此类,令人惊叹的动态 Ruby的能力是 有吸引力。但是——如果我们在说话的话 关于大型应用程序,由 人多,养得连 更多,包括各种各样的图书馆 从不同的来源,并且需要 在客户端站点进入生产…… 好吧,我不想要那种语言 非常有活力,非常感谢。 我讨厌图书馆这个想法 不知不觉中打破了其他无关 那些依赖于这些字符串的 不同,这才是深度 并深深隐藏着“通道”,在两者之间 看起来分开的代码段和 应该分开,那是拼法 D-e-a-t-h。 通过让任何模块影响 任何其他“偷偷摸摸”的行为 的语义变异能力 内置类型只是一个坏主意 生产应用程序编程,

如果我必须使用Ruby来处理这么大的 申请,我会试着依靠 编码风格的限制,很多 测试(要在任何时候重新运行 改变,甚至应该完全改变 无关…),诸如此类 禁止使用此语言特性。 但是没有这个功能 第一名就更好了,在我 意见——就像Python本身一样 是一种更好的语言 应用程序编程,如果一定 内置的数量可以被“钉住” down”,所以我知道。 Len ("ciao")是4(而不是having 潜意识里担心是否 有人修改了名字的绑定 内置命令模块中的'len'…)。 我真心希望Python最终能做到

但是问题不大,因为 重新绑定内置程序是相当困难的 已弃用,也是一种罕见的做法 在Python中。在Ruby中,它给我的印象是 major——就像过于强大 其他语言的宏功能 (比如,迪伦)表现相似 在我看来是有风险的(我确实希望如此 巨蟒从来没有这么强大过 宏系,无论诱惑 让人们定义自己的 领域特定的小语言 嵌入语言本身”——它 会影响巨蟒的精彩吗 应用的实用性 编程,通过呈现一个 “诱人的讨厌鬼” 潜伏在每一个角落的修补匠 程序员的心…)。< / p >

亚历克斯

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

使用货物你可以“需要库,但不会弄乱名称空间”。

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

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

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

在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和Jedi

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

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

def kick
puts "kick executed."
end

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

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

在Ruby中,如果你需要一个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获得了正确的继承!

语法不是一件小事,它直接影响我们的思维方式。它还直接影响我们为所使用的系统创建的规则。作为一个例子,我们有运算的顺序,因为我们写数学方程或句子的方式。数学的标准符号允许人们以多种方式阅读,并且对同一个方程得出不同的答案。如果我们使用前缀或后缀表示法,我们就会创建规则来区分要操作的数字是什么,而不仅仅是计算值的顺序。

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

我发现,如果条件是,那么编写我希望发生某些事情的条件会更容易,用Ruby中的unless语句编写要比用Ruby或其他语言中语义等效的“if-not”构造简单得多。如果人们今天使用的大多数语言的功能都是相同的,那么每种语言的语法又怎么能被认为是微不足道的事情呢?除了块和继承机制等特定功能之外,语法是语言中最重要的部分,而不是表面的东西。

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

我很惊讶没有人提到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社区那样令人讨厌,但仍然如此。

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

  1. “更安全”的全局变量
  2. 这是将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就使用它。