有很多关于Python和Ruby的讨论,我都发现它们完全没有帮助,因为它们都围绕着为什么X特性在Y语言中很糟糕,或者声称Y语言没有X,尽管事实上它有。我也确切地知道为什么我更喜欢Python,但这也是主观的,对任何人的选择都没有帮助,因为他们可能与我在开发方面的品味不同。
因此,客观地列出这些差异将是有趣的。所以没有“Python的lambdas很糟糕”。相反,解释Ruby的lambda能做而Python不能做的事情。没有主体性。示例代码很好!
请不要在一个答案上有几个不同之处。然后给你认为正确的选项投票,把你认为不正确的(或主观的)选项投下。此外,语法上的差异也不有趣。我们知道Python对缩进的处理就像Ruby对括号和结束的处理一样,@在Python中被称为self。
更新:现在这是一个社区维基,所以我们可以在这里添加大的区别。
在Ruby中,类主体中已经有了对类(self)的引用。在Python中,直到类构造完成之后才有对类的引用。
一个例子:
class Kaka
puts self
end
self在本例中是类,这段代码将打印出“Kaka”。在Python中,无法打印类名或以其他方式从类定义体(在方法定义之外)访问类。
这使您可以开发核心类的扩展。下面是一个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拥有一流的regexp、$-variables、awk/perl逐行输入循环和其他特性,这些特性使它更适合编写小型shell脚本,这些脚本可以转换文本文件或充当其他程序的粘合代码。
多亏了callcc语句。在Python中,您可以通过各种技术创建continuation,但语言中没有内置的支持。
通过“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
尽管原理不同,结果却惊人地相似。
myList.map(&:description).reject(&:empty?).join("\n")
Python:
descriptions = (f.description() for f in mylist)
"\n".join(filter(len, descriptions))
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]
将其与上面的块示例进行对比。
在Ruby中,当你导入带有require
的文件时,该文件中定义的所有内容都将在全局命名空间中结束。这会导致名称空间污染。解决方案就是ruby模块。但是如果使用模块创建名称空间,则必须使用该名称空间访问包含的类。
在Python中,该文件是一个模块,您可以使用from themodule import *
导入其包含的名称,从而在需要时污染名称空间。但是你也可以用from themodule import aname, another
导入选定的名称,或者你可以简单地import themodule
,然后用themodule.aname
访问这些名称。如果你想在你的命名空间中有更多的层,你可以有包,包是包含模块和__init__.py
文件的目录。
文档字符串是附加到模块、函数和方法的字符串 在运行时内省。这有助于创建帮助命令和 自动文档。< / 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 示例使用从文件中检索
Ruby没有(“故意的”——参见Ruby的网站看看这里是如何在Ruby中完成的)。它将模块概念重用为一种抽象类。
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"}
在Ruby中也可以创建类似于装饰器的东西,也可以认为它们不像在Python中那样必要。
Ruby需要“end”或“}”来关闭所有作用域,而Python只使用空白。在Ruby中,最近有一些尝试只允许空格缩进http://github.com/michaeledgar/seamless