关于Python与Ruby的讨论很多,我都发现它们完全无济于事,因为它们都绕开了为什么功能X吸收了语言Y或声称语言Y没有X的事实,尽管实际上确实如此。我也确切地知道为什么我偏爱Python,但这也是主观的,并且不会帮助任何人选择,因为他们在开发中的品味可能不如我。
因此,客观列出差异是很有趣的。因此,没有“ Python的lambdas很烂”。相反,请解释Ruby的lambda可以做什么,而Python则不能。没有主观性。示例代码很好!
请在一个答案中没有几个差异。并投票支持您所知道的正确和不正确(或主观)的投票。同样,语法上的差异也不是很有趣。我们知道Python用缩进来做,而Ruby用括号来做,而@在Python中被称为self。
更新:这是现在的社区Wiki,因此我们可以在此处添加较大的差异。
Ruby在类主体中有一个类引用
在Ruby中,您已经在类主体中引用了该类(自身)。在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具有一流的正则表达式,$变量,awk / perl逐行输入循环以及其他功能,使其更适合于编写小型shell脚本,这些脚本会压缩文本文件或充当其他程序的粘合代码。
Ruby具有一流的延续性
感谢callcc声明。在Python中,您可以通过各种技术来创建延续,但是该语言没有内置支持。
红宝石有块
使用“ do”语句,您可以在Ruby中创建一个多行匿名函数,该函数将作为参数传递给do前面的方法,然后从那里调用。在Python中,您可以通过传递方法或使用生成器来实现。
红宝石:
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中将创建一个生成器。
红宝石:
def themethod
yield 5
end
themethod do |foo|
puts foo
end
蟒蛇:
def themethod():
yield 5
for foo in themethod():
print foo
尽管原理不同,但结果却非常相似。
Ruby更轻松地支持功能样式(类似管道)的编程
myList.map(&:description).reject(&:empty?).join("\n")
蟒蛇:
descriptions = (f.description() for f in mylist)
"\n".join(filter(len, descriptions))
Python具有内置的生成器(如上所述,它们像Ruby块一样使用)
Python支持该语言的生成器。在Ruby 1.8中,您可以使用generator模块,该模块使用延续从一个块中创建一个generator。或者,您可以只使用block / proc / lambda!此外,在Ruby 1.9中,光纤是并且可以用作生成器,而Enumerator类是内置的生成器4
docs.python.org包含以下生成器示例:
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
将此与上面的块示例进行对比。
Python具有灵活的名称空间处理
在Ruby中,当您使用导入文件时require
,该文件中定义的所有内容都将最终存储在全局名称空间中。这会导致名称空间污染。解决方案是Rubys模块。但是,如果使用模块创建名称空间,则必须使用该名称空间来访问所包含的类。
在Python中,该文件是一个模块,您可以使用导入其包含的名称from themodule import *
,从而根据需要污染名称空间。但是,您也可以使用导入刚刚选择的名称,from themodule import aname, another
也可以简单地使用导入import themodule
名称themodule.aname
。如果要在名称空间中使用更多级别,则可以有包,包是带有模块和__init__.py
文件的目录。
Python具有文档字符串
文档字符串是附加到模块,函数和方法的字符串,可以在运行时自省。这有助于创建诸如help命令和自动文档之类的东西。
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 示例use在运行时从文件中检索它们。
Python具有多重继承
Ruby不会(“故意”-请访问Ruby的网站,在这里查看它是如何在Ruby中完成的)。它确实将模块概念作为一种抽象类重用。
Python具有列表/字典理解
蟒蛇:
res = [x*x for x in range(1, 10)]
红宝石:
res = (0..9).map { |x| x * x }
蟒蛇:
>>> (x*x for x in range(10))
<generator object <genexpr> at 0xb7c1ccd4>
>>> list(_)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
红宝石:
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'}
红宝石:
>> 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