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


263

关于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


2
关于多重继承,仅说“ Ruby not”是不明智的。我想不出您可以在Python中使用多重继承做的任何事情,而在模块/“ mixin继承”中无法在ruby中做的事情。(甚至有争议的是,仅包含普通模块就是多重继承。)
Logan Capaldo

2
您可以通过其他方式执行相同的操作是一个不成立的参数。您可以通过其他方式在这里进行所有操作。而且由于模块不是类,所以它不是多重继承。欢迎您为Python多重继承与Rubys模块一起完成代码示例提供帮助。
Lennart Regebro

3
模块不是类,但类是模块。%ruby -e'p Class <
Module'true

8
-1不幸的是,这个问题没有达到目标,大多数所谓的差异根本不是差异,而且错误信息比比皆是!
偏差

2
实际上,模块包括多重继承,不仅在概念上,而且在Ruby解释器中的实际实现中也是如此。当包含Ruby模块时,它将以与超类完全相同的方式注入到继承链中。方法分辨率是相同的。在Ruby中,多个模块包括多个继承。任何想在语义上与多重继承争辩为“不一样的东西”的人都只是腐。如果效果相同并且很容易实现,那么什么不是“同一件事”又有什么意义呢?没有区别的区别。
戴夫·西姆斯

Answers:


34

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,但由于缺少一些有用的语法糖,因此它没有块。但是,至少有一种方法可以临时获得它。例如,请参阅此处


6
@Lennart:除了您的例子之外,简直太可怕了,从语法上讲也是错误的。

2
@unbeknow:对,对。但是,如果那是一个功能而不是打印功能,那将奏效。在python 3中,此方法有效:[[[1,2,3,4]中e的print(e + 5)]当涉及到可怕性时,我认为上面的ruby代码太可怕了,因此这显然是主观的,因此不是这个问题的一部分。@John我不是说它是等效的,不是说与您的示例有什么区别并不明显。@Bastien,不,但是您可以做类似的事情并不意味着它们是相同的。即使有其他方法也应列出此处的差异。
Lennart Regebro

22
我是Python程序员。我想看一个例子,说明Ruby块如何帮助您编写比Python更简洁或更漂亮的内容,因为它没有块。您的示例可以这样写:对于[1、2、3、4]中的i:print(i + 5)。它不使用块,但每个示例都简洁而美丽。
曼努埃尔·塞隆

10
@ Manuel,procs对于将函子附加到无法平凡的非平凡数据结构(树,图形等)很有用,因此需要特殊的迭代器来横向。块是匿名proc,可让您在一个表达式中实现函子(相对于define然后实现),这极大地加快了编码过程并阐明了意图。例如,如果您要创建一个图形数据结构,则可以定义一个“每个”迭代器,然后混合Enumerable,这将立即为您提供数十个迭代器(sort,all?,any?,grep)的访问权限。现在给你打电话块...
偏置

4
@RommeDeSerieux,因为它需要用语言命名!而且,它是一个函数对象,而不是一个函数。让我们看一下Ruby Docs:“ Proc对象是已绑定到一组局部变量的代码块”,因此匿名Proc只是,而且肯定不仅仅是一个函数!
偏差

28

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包装函数以将其视为变量,但是它不再是函数;它是带有“调用”方法的对象。

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

8
你很困惑。一流的对象是通过Assign:分配的x = y,而不是通过调用的self.class.send(:define_method, :func, method(:func2))。您的“反例”展示了Ruby的功能不是一流的。如果您不同意,请随时发布您自己的答案;不要让我困惑。
格伦·梅纳德

7
def ... end在ruby中定义的东西不是函数。它们是方法(您的定义方法Kernel)。方法可以是未绑定的(使用#method方法),然后是对象。红宝石与功能最接近的是Proc实例,它们也是对象,并且可以传递或调用。Proc正如John Feminella 在他的答案中所讨论的它还具有用于将单个回调传递给方法的特殊语法。
风铃草

4
@Glenn:我明白您的意思,但是我对Ruby的重新定义功能的说法感到困惑-方法是一个独立的语义概念。如果要玩定义游戏,则最重要的代码是过程,而不是函数。我并不是想变得困难,只是我相信定义和准确性很重要。我同意操纵UnboundMethodPITA 是可以的。
风铃草

5
@格伦:情人眼里是情人。尽管如此,方法通过满足定义是一流的对象(在这种情况下,我指的是Wikipedia定义)。也许,您对头等舱有其他定义?他们是否需要白金飞行常客卡才能升至头等舱?
偏差

4
@Glenn查看SO常见问题解答部分“其他人可以编辑我的东西吗?!” -这是社区Wiki。
偏置

26

最终,所有答案都将在一定程度上是主观的,到目前为止发布的答案几乎证明,您无法以同样不错的方式(如果不是相似的方式)指向其他语言无法实现的任何功能,因为这两种语言都很简洁明了。

我喜欢Python的语法。但是,您必须比语法更深入一点,才能找到Ruby的真正魅力。Ruby的一致性具有禅宗般的美。虽然没有任何简单的示例可以完全解释这一点,但我将在此处尝试提出一个示例以解释我的意思。

反转此字符串中的单词:

sentence = "backwards is sentence This"

在考虑如何做时,请执行以下操作:

  1. 把句子分成单词
  2. 反转字
  3. 重新将单词重新组合成字符串

在Ruby中,您可以这样做:

sentence.split.reverse.join ' '

正如您所想的那样,以相同的顺序依次调用一个方法。

在python中,它将看起来像这样:

" ".join(reversed(sentence.split()))

这不难理解,但流程不尽相同。主题(句子)埋在中间。这些操作是功能和对象方法的混合。这是一个简单的示例,但是在真正使用和理解Ruby时,尤其是在非琐碎的任务上,人们发现了许多不同的示例。


1
我同意。当我编写Ruby时,它似乎自然流淌,因此“ zenlike”是个好词。
Tin Man 2010年

18

Python具有“我们都在这里成年”的心态。因此,您会发现Ruby具有类似常量的功能,而Python没有(尽管Ruby的常量只会发出警告)。Python的思维方式是,如果您想使某些内容不变,则应将变量名全部大写,而不要更改它。

例如,Ruby:

>> PI = 3.14
=> 3.14
>> PI += 1
(irb):2: warning: already initialized constant PI
=> 4.14

蟒蛇:

>>> PI = 3.14
>>> PI += 1
>>> PI
4.1400000000000006

19
哈..这只是提醒我,至少在python 2. *中,您能够执行“ True,False = False,True” ...我相信他们已经在python 3.0中正确地解决了这一点...您应该这样做被阻止做。
汤姆

11
就我个人而言,我喜欢该语言强制执行的严格准则,因为它可使使用该语言编写的所有代码保持一致。它迫使您遵循这些准则,并且开发人员在阅读您的代码后可以一目了然。虽然大多数Python编码人员使用相同的通用“样式”,但我已经看到了一些相当大的不一致之处,而这在Ruby中是不可能的。
Sasha Chedygov

8
@bias-我不确定你为什么要拒​​绝我。这个答案不同意或不同意python的做事方式。这只是事实的陈述。
杰森·贝克

13
@Jason“我们都是大人了”是对事实的陈述吗?我想称其为围绕某个功能的观点,因此投了反对票。
偏置

7
@bias-说“我们在这里都是大人”并不意味着什么。这是一个非正式的Python座右铭,我相信可以在这里得到最好的解释:mail.python.org/pipermail/tutor/2003-October/025932.html
Evan Porter

18

您只能从Python中的模块导入特定功能。在Ruby中,您将导入整个方法列表。您可以在Ruby中“取消导入”它们,但这不是全部。

编辑:

让我们来看看这个Ruby模块:


module Whatever
  def method1
  end

  def method2
  end
end

如果您将其包含在代码中:


include Whatever

您会看到method1method2都已添加到您的名称空间中。您不能仅导入method1。您要么同时导入它们,要么根本不导入它们。在Python中,您只能导入您选择的方法。如果有这个名字,也许会叫做选择性导入?


2
啊对!Python喜欢名称空间。Ruby不是这样吗?你没有import bla; bla.foo()Ruby吗?
Lennart Regebro

2
您只能导入函数a,而不能导入其中的所有函数。例如,如果您包含一个声明3个非静态函数的Ruby模块,则可以将它们全部包含在名称空间中。在python中,您必须从模块import *编写。
地理位置:

6
这不是导致很多名称空间混乱吗?
Lennart Regebro

1
我认为是的。那就是我讨厌Ruby模块的原因。
地理位置:

8
Ruby实际上没有与python相同的模块系统。require基本上是文本包含的,并进行了一些检查以检查是否包含重复项。您可以(ab)将模块用作名称空间,但module实际上有点用词不当。模块基本上类SAN的newallocate方法。它们最适合作为基于每个类/对象共享代码的方法,而不是作为分区库或跨程序共享代码的机制。
Logan Capaldo

16

从Ruby的网站

与Python相似,在Ruby中,...

  • 有一个交互式提示(称为irb)。
  • 您可以在命令行上阅读docs(使用ri命令而不是pydoc)。
  • 没有特殊的行终止符(通常的换行符除外)。
  • 字符串文字可以跨越多行,例如Python的三引号字符串。
  • 方括号用于列表,大括号用于字典(在Ruby中称为“哈希”)。
  • 数组的工作原理相同(添加它们会构成一个长数组,但是像这样组成它们 a3 = [ a1, a2 ]得到一个数组数组)。
  • 对象是强类型和动态类型的。
  • 一切都是对象,变量只是对象的引用。
  • 尽管关键字有些不同,但是例外的作用大致相同。
  • 您已经拥有嵌入式doc工具(Ruby称为rdoc)。

与Python不同,在Ruby中,...

  • 字符串是可变的。
  • 您可以创建常量(不希望更改其值的变量)。
  • 有一些强制的大小写约定(例如,类名以大写字母开头,变量以小写字母开头)。
  • 列表容器只有一种(数组),并且是可变的。
  • 双引号字符串允许转义序列(如\ t)和特殊的“表达式替换”语法(可让您将Ruby表达式的结果直接插入其他字符串中,而不必“添加” +“字符串” +“在一起”) 。单引号字符串类似于Python的r“原始字符串”。
  • 没有“新样式”和“旧样式”类。只是一种。
  • 您永远不会直接访问属性。使用Ruby,这就是所有方法调用。
  • 方法调用的括号通常是可选的。
  • 有公共的,私有的和受保护的用于强制访问,而不是Python的_voluntary_ underscore __convention__
  • 使用“ mixin's”代替多重继承。
  • 您可以添加或修改内置类的方法。两种语言都可以让您随时打开和修改类,但是Python阻止了对内置函数的修改,而Ruby则不允许。
  • 您将获得true和false而不是True和False(并且使用nil代替None)。
  • 在测试真相时,只有false和nil会得出错误值。其他所有内容均正确(包括0、0.0,“”和[])。
  • 它是elsif而不是elif。
  • 这是必需的,而不是导入。否则,用法是相同的。
  • 事物上方的一行(而不是它们下方的文档字符串)上的常用注释用于生成文档。
  • 尽管有许多捷径可让您记住,但仍有许多捷径可让您快速学习。它们往往使Ruby变得有趣且非常有生产力。

2
“这是必需的,而不是导入的。否则,用法是相同的。” 似乎是完全不正确的。
Glenjamin 2011年

人们也很少使用Ruby中的Set,但是它们是内置的。因此,我可以说,stuff_in_backpack = Set.new; stuff_in_backpack <<“计算机”; stuff_in_backpack <<“鞋子”; #和集合将保留所有值而无需保证顺序。
zachaysan,2011年

12

Ruby比Python具有的脚本语言功能。在这种情况下,脚本语言意味着用于Shell脚本和常规文本操作中的“胶水代码”。

这些大多与Perl共享。一流的内置正则表达式,$-Variables,有用的命令行选项(如Perl(-a,-e)等)。

连同其简洁而优美的语法,它非常适合此类任务。

对我而言,Python更像是一种动态类型化的业务语言,它非常易于学习并且语法简洁。不像Ruby那样“酷”,但很简洁。Python对Ruby而言,对我来说,是其他库的大量绑定。绑定到Qt和其他GUI库,许多游戏支持库以及和和。Ruby少得多。尽管经常使用的绑定(例如与数据库的绑定)具有良好的质量,但我发现利基库在Python中得到了更好的支持,即使对于同一库也有Ruby绑定。

因此,我想说这两种语言都有其用途,这是定义要使用哪种语言的任务。两者都很容易学习。我并排使用它们。Ruby用于脚本编写,Python用于独立应用程序。


1
来自尚不了解Ruby的人的问题:“ $ -Variables”是什么意思?你是说全局变量吗?如果是这样,在Python中,在类或函数外部的模块中定义的变量是全局的。如果没有-有什么区别?
匿名2009年

1
Anon:如果在代码中的任何地方声明$ variable,则由于前缀,它是全局的。因此,无论在何处定义它都始终是全局的,并且始终如此。
罗伯特·K

8
不完全是,实际上我指的是预定义的变量,例如$ _,$ 1等。这些变量由ruby自身自动填充。$ _是最后读取的行。$ 1,$ 2等是最后一次匹配的正则表达式匹配。有关完整列表,请参见此处:zenspider.com/Languages/Ruby/QuickRef.html#17基本上,它是紧凑脚本的黑客。您也可以通过API调用获取所有信息,但使用$变量则更为简洁。这样的变量只是不适合Python的样式,他们故意将它们排除在外。
haffax

感谢您提供的zenspider链接-一直在寻找类似的东西,以便快速了解Ruby。
佚名

12

我不认为“ Ruby具有X而Python没有,而Python具有Y而Ruby没有”是查看它的最有用的方法。它们是非常相似的语言,具有许多共享功能。

在很大程度上,区别在于该语言使语言更加优雅和可读。使用您提出的示例,理论上两者都具有lambda,但是Python程序员倾向于避免使用lambda,并且使用它们构造的构造看起来不像Ruby那样易读或惯用。因此,在Python中,优秀的程序员将希望采用与Ruby中不同的方法来解决问题,只是因为这实际上解决问题的更好方法。


5
我同意lambda的作用范围有限,在许多情况下没有用。但是,我不认为说Python程序员像瘟疫一样避免它们是不公平的。
贾森·贝克

1
我同意lambdas经常与Python一起使用-例如与map,filter,reduce。最大的区别似乎是Python Lambda仅限于表达式,而Ruby块可以是多行并涉及语句。根据我对Ruby的了解,我的总体印象是,该功能特别使Rubyists倾向于DSL方法,而Pythonista则更可能选择创建API。我对Ruby的信息仍然很肤浅。
匿名2009年

2
@Lennart:在Ruby中一直使用多行块-比我在惯用的Python代码中看到的lambda更为频繁。有关常见示例,请参见info.michael-simons.eu/2007/08/06/rails-respond_to-method
Chuck

1
@Lennart:不,它不使用yield。(无论如何,Ruby的产量与Python完全不同-它不返回生成器。)编写代码没有任何意义for format in respond_to()。该respond_to方法没有返回任何有意义的东西,它只是响应当前的HTTP请求。该dorespond_to do一个块的开始。在该块中,我们与一个临时对象(format在此示例中标记为)交谈,该对象实现了用于响应HTTP请求的非常基本的DSL。
查克(Chuck)

3
您可以针对生成器“混合Enumerable”并立即获得30个新的精彩迭代器吗?您需要先全面了解该语言,然后才能理解为什么块/过程很棒。
偏差

12

我想提出一个原始问题的变体:“ Ruby有哪些Python没有的,反之亦然?” 它承认了令人失望的答案:“那么,用Intercal无法做到的Ruby或Python可以做什么?” 在这个级别上什么都没有,因为Python和Ruby都是庞大的皇室家族的一部分,坐在图灵近似的宝座上。

但是呢:

在Python中,优雅而良好的工作可以做得很好,而在Ruby中却不能做到如此美丽和出色的工程,反之亦然?

这可能比单纯的功能比较有趣。


充其量只是一个评论。还是我的+1
nawfal 2012年

11

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

比较

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

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

列表推导如何不是普通的Python?Python中也有一个map函数。
SilentGhost

但是Ruby中没有列表理解语法
-Dario

Python:res = map(lambda x:x * x,range(1,10))
GogaRieger,2009年

Python:res=map(2 .__rpow__, range(1,10))
John La Rooy

11

“以大写字母开头的变量将成为常量,无法修改”

错误。他们能。

您只会收到警告。


2
如果一种语言警告您进行某项操作,我认为您很可能会认为该操作“不可能”。别的就是疯狂。
porgarmingduod 2011年

11

基础设施方面:

  • 与Ruby相比,Python与C ++的集成要好得多(通过Boost.PythonSIPPy ++之类的东西),而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社区进行交互的丰富经验。我主要是为了补充这一点,希望对两者都有丰富经验的人可以放大(或拒绝)此声明。


7
您的第二点充其量是误会。您应该先看看Rack和Sinatra
Max Ogden

6
我明确指出存在其他Rails堆栈。我只是认为没有人真正在使用它们。检查Sinatra和Rack并没有完全改变这种印象。您是否真的认为,例如,Sintratra(总共94个SO问题)或Camping(总共2个SO问题),或其他任何一个,实际上都有一个真正的用户群/社区?据我所知,大多数人甚至没有现实生活中的用户。与Django(4K +)或Rails(7K +)甚至web.py进行比较。
杰克·劳埃德

1
实际上,由于其DSL,Sinatra在不同的轻量级任务中非常受欢迎。它使用较少,因为Rail的MVC提供了更多功能。Rails实际上是建立在机架上的-这就是使Phusion Passenger成为可能的原因。
替代

11

无耻地复制/粘贴自:Alex Martellicomp.lang.python邮件列表中回答了Ruby比Python有什么更好的线程。

2003年8月18日,上午10:50 Erik Max Francis写道:

“布兰登·范·凡·布朗”写道:

Ruby比Python有什么更好的选择?我确定有事 它是什么?

向Ruby人员(而不是Python人员)问这个不是更有意义吗?

可能(也可能不会)取决于一个人的目的-例如,如果一个人的目的包括对Python社区的“社会学研究”,那么向该社区提出问题很可能会证明有关该信息的揭示更多,而不是放在其他地方:-)。

我个人很高兴借此机会在上次OSCON上关注Dave Thomas的为期一天的Ruby教程。在语法差异的明显变化之下,我发现Ruby和Python惊人地相似-如果我正在计算几乎所有语言集中的最小生成树,我很确定Python和Ruby将成为合并的前两叶中间节点:-)。

当然,在Ruby中,我确实会在每个块的末尾键入愚蠢的“ end”(而不是不缩进)而感到疲倦-但是,我确实避免输入Python要求的同样愚蠢的':'。每个块的 开始,所以几乎可以洗了:-)。其他语法差异,例如'@foo'与'self.foo',或者Ruby vs Python中case的较高重要性,实际上与我无关。

毫无疑问,其他人只是基于这样的问题来选择编程语言,并且引发了最激烈的辩论-但对我而言,这只是帕金森定律中一个行动的例子(关于某个问题的辩论数量与该问题的数量成反比实际重要性)。

编辑(2010年6月19日,上午11:45之前):这也称为“为自行车棚涂漆”(或简称为“自行车棚涂漆”)-再次提及诺斯科特·帕金森,他提出了“辩论”作为“关于琐碎话题的热门辩论”的典型示例。(编辑结束)。

我确实发现语法上的差异很重要,并且对Python有利-但其他人无疑会认为相反-是“如何调用不带参数的函数”。在Python中(就像在C中一样),要调用函数,您总是要应用“调用运算符”-括号紧跟在您要调用的对象之后(在这些括号内是您在调用中传递的args,如果您没有传递参数,则括号为空)。这仅提及 任何对象,不涉及运算符,在任何上下文中都意味着仅是对对象的引用,没有特殊情况,异常,即席规则等。在Ruby中(例如在Pascal中),要调用带有WITH参数的函数,您需要传递args(通常在括号中,尽管并非总是如此)-但是,如果该函数没有args,则只需简单地提及该函数即可。这可能会满足许多人的期望(至少,毫无疑问,至少那些以前仅有编程经验的人是使用Pascal或其他具有类似“隐式调用”的语言(例如Visual Basic)的人)-但对我而言,这意味着仅提及对象可能意味着对对象的引用或对对象的调用,具体取决于对象的类型-在某些情况下,我可以 仅仅通过提及它就不能得到对对象的引用,我将需要使用明确的“给我一个对此的引用,不要称呼它!” 否则不需要的运算符。我觉得这会影响函数(或方法或其他可调用对象)的“一流”,并影响对象平滑交换的可能性。因此,对我来说,这种特定的语法差异对Ruby来说是一个严重的黑标-但我确实理解了为什么其他人会采取其他方式,即使我几乎无法强烈反对它们:-)。函数(或方法或其他可调用对象)的功能,以及顺利交换对象的可能性。因此,对我来说,这种特定的语法差异对Ruby来说是一个严重的黑标-但我确实理解了为什么其他人会采取其他方式,即使我几乎无法强烈反对它们:-)。函数(或方法或其他可调用对象)的功能,以及顺利交换对象的可能性。因此,对我来说,这种特定的语法差异对Ruby来说是一个严重的黑标-但我确实理解了为什么其他人会采取其他方式,即使我几乎无法强烈反对它们:-)。

在语法下方,我们发现了基本语义上的一些重要差异-例如,Ruby中的字符串是可变对象(例如在C ++中),而在Python中则不可改变(例如在Java中,或者我相信C#)。同样,主要根据已经熟悉的知识进行判断的人可能会认为这对Ruby有利(除非他们熟悉Java或C#,当然:-)。我,我认为不可变字符串是一个好主意(我不认为Java独立地重新发明了Python中已经存在的那个想法),尽管我也不介意具有“可变字符串缓冲区”类型(理想情况下,它比Java自己的“字符串缓冲区”具有更好的易用性);而且由于熟悉程度,我不作这样的判断-在学习Java之前, 所有数据都是不可变的,我所知道的所有语言都具有可变的字符串-但是,当我第一次看到Java中的不可变字符串的想法(我在学习Python之前就学得很好)时,它立即使我震惊,非常适合顶级编程语言的参考语义(与最适合于距离机器更近,距离应用程序更远的语言,例如C)最合适的值语义,将字符串作为一流的,内置的(漂亮的)关键)数据类型。

Ruby在基本语义上确实具有一些优势-例如,删除Python的“列表与元组”极其微妙的区别。但是大多数情况下,分数(就我而言,保持简单,是一个很大的加和微妙的,聪明的区别,是一个显着的减号)与Ruby相对(例如,同时具有封闭和半开放间隔,用符号a..b和a。表示)。 .b [任何人都想声称哪个是显而易见的?-)],这很愚蠢-当然,恕我直言!)。同样,考虑到在语言的核心上有很多相似但又细微不同的事物的人,加号(而不是减号)当然会按照我的计算方式来反加这些:-)。

这些比较不会误导您认为这两种语言是 非常不一样,请注意。他们不是。但是,如果我被要求将“ capelli d'angelo”与“ spaghettini”进行比较,然后指出这两种意大利面几乎对任何人都没有区别,并且可以在您可能要准备的任何菜肴中互换使用,那么我将不可避免地拥有进入显微镜检查长度和直径如何明显地不同,在一种情况下而不是在另一种情况下股线的末端如何逐渐变细等等,以尝试解释为什么我个人更愿意'angelo作为任何一种汤中的意大利面食,但更喜欢将意大利面条作为Pastasciutta来搭配适用于此类长而细的意大利面食形式的调味料(橄榄油,蒜末,剁碎的红辣椒和细碎的凤尾鱼,例如-但是,如果您将大蒜和胡椒切成薄片而不是切碎,那么您应该选择意大利面更健康的面条,而不是意大利面条稀薄的消失,并且建议您不要食用凤尾鱼,而应添加一些新鲜的春季罗勒[甚至-我是一个异端...!-薄荷糖...]树叶-在上菜之前的最后一刻)。糟糕,抱歉,这表明我正在国外旅行,而且有一段时间没有面食了,我想。但比喻还是相当不错的!-)-薄荷糖...]树叶-在上菜之前的最后一刻)。糟糕,抱歉,这表明我正在国外旅行,而且有一段时间没有面食了,我想。但比喻还是相当不错的!-)-薄荷糖...]树叶-在上菜之前的最后一刻)。糟糕,抱歉,这表明我正在国外旅行,而且有一段时间没有面食了,我想。但比喻还是相当不错的!-)

因此,回到Python和Ruby,我们来谈谈两个大问题(就适当的语言而言-离开了库以及其他重要辅助工具(如工具和环境,如何嵌入/扩展每种语言等),现在-它们将无法应用于每种语言的所有实现,例如,Jython与Classic Python是Python语言的两种实现!):

  1. Ruby的迭代器和代码块与Python的迭代器和生成器;

  2. Ruby的TOTAL不受限制的“动态性”,包括
    “重新打开”任何现有类(包括所有内置类)并在运行时更改其行为的能力-相对于Python庞大但 有限的 动态性,它从未改变现有的行为内置类及其实例。

就我个人而言,我认为1是一次洗礼(差异是如此之深,以至于我很容易看到人们讨厌这两种方法中的任何一种,但从我个人的角度来看,它们的优缺点几乎相同);还有2个至关重要的问题-一个使Ruby更适合“修补”的问题,但Python同样更适合用于大型生产应用程序。从某种程度上讲,这很有趣,因为两种语言都比大多数其他语言更具动态性,以至于最终它们与我的POV之间的关键区别应该取决于这一点-Ruby在这方面“达到11种”(参考当然是“ Spinal Tap”。在Ruby中我能做到!即,我可以动态地更改内置的字符串类,以便如果a == b打印“等于!\ n”,则a =“ Hello World” b =“ hello world”,否则打印“ different!\ n”,最后将打印“等于”。在python中,我无法做到这一点。出于元编程,实现实验框架等目的,Ruby的这种惊人的动态功能非常强大。 吸引人。但是-如果我们谈论的是大型应用程序,它是由许多人开发并由更多人维护的,包括来自不同来源的各种库,并且需要在客户站点上投入生产...那么,我不想一种非常动态的语言,非常感谢。我讨厌这样的想法:某些库不知不觉地打破了那些依赖于那些不同字符串的其他不相关的库-这是一种深层和深层的“通道”,在LOOK分离和应该分离的代码段之间,这意味着死亡。大规模编程。通过让任何模块“隐蔽地”影响任何其他模块的行为,对内置类型的语义进行变异的能力只是生产应用程序编程的一个坏主意,

如果我必须将Ruby用于如此大的应用程序,那么我将尝试依赖于编码样式的限制,大量的测试(只要有任何更改,都将重新运行-甚至应该完全不相关...),等等。禁止使用此语言功能。但是,我认为不首先具有该功能会更好,就像Python本身可以成为应用程序编程的一种更好的语言一样,如果可以“固定”一定数量的内置程序,那么我知道,例如len(“ ciao”)为4(而不必担心是否有人在内置模块中更改了名称“ len”的绑定...)。我确实希望Python最终能够“钉牢”其内置组件。

但是问题不大,因为重新绑定内置函数在Python中已被弃用,也是一种罕见的做法。在Ruby中,它让我感到很专业-就像 其他语言(例如Dylan)的功能过于强大一样,在我看来也存在类似的风险(我希望Python永远不会获得如此强大的宏系统, “让人们定义自己的语言中嵌入的他们自己的特定于领域的小语言”的诱惑力很重要-恕我直言,这会通过向可能的修补匠提供“有吸引力的麻烦”来削弱Python对应用程序编程的出色用处。潜伏在每个程序员的心中...)。

亚历克斯


9

其他人来自:

http://www.ruby-lang.org/zh-CN/documentation/ruby-from-other-languages/to-ruby-from-python/

(如果自该页面更新以来,我误解了任何东西,或者其中的任何一个在Ruby方面已更改,则可以随时进行编辑...)

字符串在Ruby中是可变的,而不是在Python中(通过“ changes”创建新字符串)是可变的。

Ruby有一些强制的大小写约定,而Python没有。

Python同时具有列表和元组(不可变列表)。Ruby具有与Python列表相对应的数组,但它们没有不变的变体。

在Python中,您可以直接访问对象属性。在Ruby中,总是通过方法。

在Ruby中,方法调用的括号通常是可选的,但在Python中则不是。

Ruby具有公共,私有和受保护的强制访问权限,而不是Python使用下划线和名称修饰的约定。

Python具有多重继承。Ruby具有“ mixins”。

另一个非常相关的链接:

http://c2.com/cgi/wiki?PythonVsRuby

特别是与Alex Martelli的另一个好链接的链接,Alex Martelli在SO上也发布了很多很棒的东西:

http://groups.google.com/group/comp.lang.python/msg/028422d707512283


1
在ruby中,您可以简单地冻结数组以将其更改为不可变的内容
user163365'9

Alex Martelli的
精彩

8

我不确定,因此我首先将其添加为答案。

Python将未绑定方法视为函数

这意味着您可以通过theobject.themethod()或调用方法TheClass.themethod(anobject)

编辑:尽管方法和函数之间的差异在Python中很小,在Python 3中不存在,但是在Ruby中也不存在,仅因为Ruby没有函数。定义函数时,实际上是在Object上定义方法。

但是您仍然不能采用一个类的方法并将其作为函数调用,您将不得不将其重新绑定到要调用的对象上,这更加令人费解。


Ruby根本没有功能。就是说,TheClass.instance_method(:themethod).bind(anobject).call将是等效的红宝石。
Logan Capaldo

哦。因此,当您定义不在显式类上的函数时,会有某种魔术主类?
Lennart Regebro

是的,在顶层定义的方法是的私有方法Object
Logan Capaldo

1
FWIW,似乎在Python中,函数和方法实际上是同一类型,并且它们的不同行为来自于描述符:users.rcn.com/python/download/…
巴斯蒂安·莱纳德(BastienLéonard)2009年

1
但是,如果将其绑定到对象,则它不是未绑定的。咄。:-)而且它们在Python中也是一样。只是Ruby实际上没有功能。这意味着我的说法是正确的。您可以像在Python中一样调用未绑定方法。这实际上是有用的,例如,这意味着您可以在不具有该类的对象上调用在该类上定义的方法,这有时很有用。
Lennart Regebro

7

我想提到Python描述符API,该API允许一个自定义对象到属性的“通信”。还值得注意的是,在Python中,可以通过覆盖通过方法的默认实现提供的默认值来自由实现另一种协议__getattribute__。让我提供有关上述内容的更多详细信息。描述是在普通类__get____set__和/或__delete__方法。当解释器遇到类似的内容时anObj.anAttr,将执行以下操作:

  • __getattribute__的方法anObj被调用
  • __getattribute__ 从类字典中检索anAttr对象
  • 它检查abAttr对象是否具有__get____set____delete__可调用对象
  • 上下文(即调用方对象或类,以及值,而不是后者,如果有设置器的话)被传递给可调用对象
  • 返回结果。

如前所述,这是默认行为。可以通过重新实现自由更改协议__getattribute__

该技术比装饰器功能强大得多。




5

Python具有文档字符串,而ruby没有...或者,如果没有,则无法像在python中那样容易地访问它们。

附言 如果我错了,请留下一个例子?我有一个解决方法,可以很容易地将其猴子类拼凑到类中,但是我想以“本机方式”使用文档字符串有点功能。


3
没有文档字符串,但是有RDoc。是的,不是那么容易获得,但不是100%隐藏。
奥马尔·库雷希

Ruby不使用文档字符串。它以不同的方式进行文档编制。
Chuck

1
奥马尔:是的,我了解rdoc但了解afaik,它们不像python的docstring那样“易于访问”。例如,如果我有一个类,并且我想从该类中输出rdoc文档,则它的工作量很大。我所做的是,我生成ri文档,并尝试保持up2date,然后获取该信息本身。绝对不是与python的文档字符串相同
。.– rasjani

文档字符串可用于提供文档测试。Ruby是否有类似的东西?
Lennart Regebro

2
是的,它叫做“ Ruby Doctest”。就doctest而言,真正重要的是您在某个地方具有可读的文档,其中包括可测试的代码片段-无论是在文档字符串还是在注释中,这都没有关系。
Chuck

5

Ruby在命令行中逐行循环输入文件('-n'标志),因此可以像AWK一样使用。这个Ruby一线:

ruby -ne 'END {puts $.}'

将计数像AWK一线式的行:

awk 'END{print NR}'

Ruby通过Perl获得了此功能,Perl从AWK那里获得了它,这是使系统管理员可以使用Perl的一种方式,而不必更改他们的工作方式。


1
我想补充一点,Python的命令行支持相当弱。除了缺少自动循环外,您不能将几条语句放在一行中并将其作为单字符串命令行参数传递给解释器。至少我没有这样做。
ThomasH

当然可以。但是,您(与任何其他语言一样)都需要用引号引起来。
Lennart Regebro 09年

不建议在命令行上使用Python,因为如果要使用Python,则必须明确一些内容(例如sys.stdin)python -c "import sys; print len(list(sys.stdin))"
u0b34a0f6ae 2009年

5

Ruby有Sigils和Twigils,Python没有。

编辑:这是我忘记的一个非常重要的事情(毕竟,前一个只是发火了一点:-p):

Python具有JIT编译器(Psyco),一种用于编写更快的代码的低级语言(Pyrex)和添加内联C ++代码(Weave)的能力。


是的,但这只是语法。
Lennart Regebro

6
好吧,如果您想走这条路:两者都是图灵完备的。其他所有内容只是语法。
约尔格W¯¯米塔格

是的和importax语法的不同;-)
fortran

1
如果您编写@foo或self.foo,它有多重要?
Lennart Regebro

1
@Jörg:好吧,那就叫“语法”以外的东西吧。关键是@foo和self.foo的作用相同,实际上不是Ruby具有的功能,而Python没有。
Lennart Regebro

5

我的python生锈了,所以其中一些可能在python中,我只是一开始就不记得/从未学过,但是这里是我想到的前几个:

空格

Ruby处理空白完全不同。对于初学者,您不需要缩进任何内容(这意味着使用4个空格或1个制表符都没有关系)。它还执行智能线路连续,因此以下内容有效:

def foo(bar,
        cow)

基本上,如果您以运算符结尾,它将找出正在发生的事情。

混合蛋白

Ruby具有可以扩展实例而不是完整类的mixin:

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实用程序员指南》


您的第二个示例foo(1,c = 5)不执行您认为的操作。Ruby没有命名参数。
horseyguy

5
Python 在方括号内具有隐含的行连续性([{
u0b34a0f6ae 2009年

5

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

一个例子:

class Kaka
  puts self
end

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


您能否为您的第一点提供更多详细信息(例如代码)?
卢瓦克·沃尔夫

我补充说,示例代码是一个好主意,即使这种情况很简单。
Lennart Regebro

@SilentGhost:我想不出现在还不是很模糊的一个。:)
Lennart Regebro

您可以在python中的类内访问类名:class foo():def init __(self):print self .__ class .__ name__
txwikinger 2009年

1
@txwikinger:是的,但是不在类的主体之内,它是在与class语句同时执行的。
巴斯蒂安·莱奥纳德(BastienLéonard)2009年

4

语法不是一件小事,它直接影响我们的思维方式。它也直接影响我们为使用的系统创建的规则。例如,由于我们编写数学方程式或句子的方式,我们具有运算顺序。数学的标准表示法允许人们以多种方式阅读它,并在给定相同方程的情况下得出不同的答案。如果我们使用前缀或后缀表示法,那么我们将创建规则以区分要操纵的数字,而不是仅具有计算值顺序的规则。

标准表示法清楚地表明了我们在谈论什么数字,同时使它们的计算顺序不明确。前缀和后缀表示法在使数字含糊不清的同时,使计算明文的顺序变得容易。如果不是因为语法空白引起的困难,Python就已经有了多行lambda。(确实存在一些建议,无需添加显式的块定界符就可以拉出此类内容。)

我发现在条件为的情况下编写条件(如果条件为假)要比在Ruby或其他语言中用语义上等效的“ if-not”构造容易得多,而用Ruby语句中的else语句更容易编写条件。如果当今人们使用的大多数语言的力量相等,那么如何将每种语言的语法视为琐碎的事情呢?在诸如块和继承机制等特定功能之后,语法是语言最重要的部分,这并不是肤浅的事情。

肤浅的是我们赋予句法的美的美学特质。美学与我们的认知如何运作,语法无关。


不论代表如何,此“评论”的长度是评论所允许的长度的三倍。
Andrew Grimm

实际上,这对我来说似乎很好。编辑掉“这是一条评论”位。
比尔蜥蜴

3

惊讶地发现红宝石的“方法缺失”机制一无所获。我将提供Rails中find_by _...方法的示例,作为该语言功能强大功能的示例。我的猜测是可以在Python中实现类似的功能,但据我所知它本身并不存在。


Python具有get_attribute,它基本上完成了与Ruby的method_missing相同的任务。
mipadi

3
为什么在任何地方提到ruby时python开发人员总是会受到如此严重的伤害?您不能否认这不是事实。
aarona 2010年

method_missing在某些情况下可以在Python中进行仿真:class M(): def __getattr__(self, n): return lambda: "Missing! " + n; M().hi()。但是,有一些细微的差别,我怀疑它在Python中是惯用语言的:-)

1
@DJTripleThreat:我否认这是真的。
Lennart Regebro 2011年

3

Paul Graham的累加器生成器问题证明了Python和Ruby在lambda上的另一个区别。转载在这里:

编写一个具有数字n的函数foo,并返回一个具有数字i的函数,并返回以i递增的n。注意:(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 lambda比Python更强大。


3
您无法在Python中递增数字,因此这种限制毫无意义。在Python中,数字是不可变的。如果我们改为“ plus”,则该类是不必要的。因此,这并没有证明有关lambda差异的任何信息,而是数字工作方式的差异。除非您当然创建一个可变数字类。:)
Lennart Regebro

2
限制是为了阐明所需的行为。问题要求的是:f = foo(10)f(2)>> 12 f(3)>> 15 ... lambda {| i | n + i}给出:f = foo(10)f(2)>> 12 f(3)>> 13 ...在Ruby中数字也是不可变的-例如,您不能说2 + = 1。n + = 1在常规Python函数中很好,但不是lambda。因此,问题在于“ n”是什么,它是在调用函数并形成lambda时创建的,可以在lambda中进行赋值(而不只是表达式),并且可以保存n的值在多个通话中。
dormsbee 2010年

我认为您不需要在Python中花那么多的篇幅。可以在其他功能中定义功能。def foo(n): def f(i): return n + i return f
FMc

2
但是仍然不一样,您的示例与上面的注释中的Python lambda等效。Ruby版本创建一个lambda来保持两次调用之间的状态。您发布的示例允许您为n配置一个起始值,但是foo返回的函数将始终具有该起始值。Ruby版本增加。因此,假设f = foo(10)。Python的版本:F(1)=> 11,F(1)=> 11.红宝石版本f.call(1)=> 11,f.call(1)=> 12
dormsbee

def foo(n): L=[n] def f(i): L[0] += i return L[0] return f。在Python3中,您可以使用nonlocal关键字。
jfs

3

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是始终附加的影响。


3
“ Ruby仅定位参数是因为函数声明中的b = 2是始终附加的情感”甚至意味着什么?
horseyguy

3
Dunno您生活在哪个星球上,但是def my_method(param1, optional = false)可以在Ruby 1.8.6、1.8.7和1.9中工作!
罗伯特·K

5
邪恶的跳蚤以及支持他的评论的人,您对这个例子的关注度还不够。他可以跳过调用中的b参数,func并且仍保持其默认值。也就是说,b是签名中的第二个参数,但是他可以通过在第二个参数前面加上前缀来跳过它c=。Ruby使用散列对此进行模拟,但是并不完全相同。
maček

2

Ruby嵌入了文档:

 =begin

 You could use rdoc to generate man pages from this documentation

 =end

5
文档字符串最终成为您设置它们的方法/类的一部分。所以,你可以做帮助(类),它会告诉你的文档字符串,等等
伦纳特Regebro


2

在Ruby中,当您导入带有require的文件时,该文件中定义的所有内容都将最终存储在全局名称空间中。

使用Cargo,您可以“在不干扰名称空间的情况下要求提供库 ”。

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

这本来应该是评论,而不是新的答案。
Lennart Regebro 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.