小编典典

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

all

有很多关于 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 具有一流的正则表达式、$ 变量、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

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
中,您可以使用生成器模块,该模块使用延续从块中创建生成器。或者,您可以只使用块/proc/lambda!此外,在 Ruby 1.9 中,Fiber
可以用作生成器,并且 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 有文档字符串

文档字符串是附加到模块、函数和方法的字符串,可以在运行时进行自省。这有助于创建诸如帮助命令和自动文档之类的东西。

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示例在运行时从文件中检索它们

Python有多重继承

Ruby 没有(“故意”——参见 Ruby 的网站,在此处查看它是如何在 Ruby
中完成的
)。它确实将模块概念重用为一种抽象类。

Python 有列表/字典推导

Python:

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

红宝石:

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]

红宝石:

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


阅读 71

收藏
2022-05-16

共1个答案

小编典典

您可以在 Ruby 和 Python 的类定义中包含代码。但是,在 Ruby 中,您有一个对类 (self) 的引用。在 Python
中,您没有对该类的引用,因为该类尚未定义。

一个例子:

class Kaka
  puts self
end

在这种情况下,self 是类,这段代码将打印出“Kaka”。无法打印出类名或以其他方式从 Python 中的类定义主体访问该类。

2022-05-16