Locked 。这个问题及其答案是locked /help/locked-posts 因为这个问题是题外话,但却具有历史意义。目前不接受新的答案或互动。
关于 Python 与 Ruby 的讨论有很多,我都发现它们完全没有帮助,因为它们都围绕着为什么 X 功能在 Y 语言中很糟糕,或者声称 Y 语言没有 X,尽管事实上它有。我也确切地知道为什么我更喜欢 Python,但这也是主观的,并且不会帮助任何人选择,因为他们在开发方面的品味可能与我不同。
因此,客观地列出这些差异是很有趣的。所以没有“Python 的 lambda 很糟糕”。相反,请解释 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
您可以在任何序列(不仅仅是字符串)上使用它。为了使用它,你应该导入它明确地 e.g., from some_module import starts_with
.
Ruby 具有类似 Perl 的脚本功能
Ruby 具有一流的正则表达式、$-变量、awk/perl 逐行输入循环和其他功能,使其更适合编写小型 shell 脚本,这些脚本可以处理文本文件或充当其他程序的粘合代码。
Ruby 拥有一流的延续
感谢 callcc 声明。在 Python 中,您可以通过各种技术创建延续,但该语言没有内置支持。
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 中,您可以使用生成器模块,该模块使用延续从块创建生成器。或者,您可以只使用 block/proc/lambda!此外,在 Ruby 1.9 中,Fibers 是并且可以用作生成器,并且 Enumerator 类是一个内置生成器4 http://wiki.github.com/rdp/ruby_tutorials_core/enumerator
docs.python.org http://docs.python.org/tutorial/classes.html#generators 有这个生成器示例:
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
file.
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 在运行时从文件中检索它们使用示例 http://github.com/rdp/ri_for
Python具有多重继承
Ruby 没有(“故意”——参见 Ruby 的网站,看看这里是如何在 Ruby 中完成的 http://codeidol.com/other/rubyckbk/Modules-and-Namespaces/Simulating-Multiple-Inheritance-with-Mixins/ )。它确实将模块概念重用为一种抽象类。
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 http://github.com/michaeledgar/seamless