从Ruby学习Python;异同

时间:2011-01-22 16:24:54

标签: python ruby

我非常了解Ruby。我相信我现在可能需要学习Python。对于那些了解两者的人来说,两者之间的概念是相似的,有什么不同?

我正在寻找一个类似于我为Learning Lua for JavaScripters编写的引物的列表:简单的事情,如空白意义和循环结构; Python中nil的名称,以及哪些值被视为“真实”;使用相当于mapeach,或者嘟嘟 somethingaboutlistcomprehensions mumble 标准是不是惯用的?< / p>

如果我得到了各种各样的答案,我很乐意将它们汇总到社区维基中。或者你们都可以互相争斗,试图创造一个真正的综合名单。

编辑:要明确,我的目标是“正确”和惯用的Python。如果有一个等价于inject的Python,但没有人使用它,因为有更好/不同的方法来实现迭代列表和累积结果的常用功能,我想知道你是怎么做的。也许我会用一系列共同目标来更新这个问题,如何在Ruby中实现它们,并询问Python中的等价物是什么。

5 个答案:

答案 0 :(得分:150)

以下是我的一些主要区别:

  1. Ruby有块; Python没有。

  2. Python有功能; Ruby没有。在Python中,您可以使用任何函数或方法并将其传递给另一个函数。在Ruby中,一切都是方法,方法不能直接传递。相反,你必须将它们包装在Proc中以传递它们。

  3. Ruby和Python都支持闭包,但以不同的方式。在Python中,您可以在另一个函数中定义一个函数。内部函数具有对外部函数的变量的读访问权,但不具有写访问权。在Ruby中,您可以使用块定义闭包。闭包具有对外部作用域的变量的完全读写访问权。

  4. Python有列表推导,非常具有表现力。例如,如果您有一个数字列表,则可以编写

    [x*x for x in values if x > 15]
    

    获取所有大于15的值的方块的新列表。在Ruby中,您必须编写以下内容:

    values.select {|v| v > 15}.map {|v| v * v}
    

    Ruby代码感觉不那么紧凑。它也没那么高效,因为它首先将values数组转换为包含大于15的值的较短中间数组。然后,它获取中间数组并生成包含中间体方块的最终数组。然后抛出中间阵列。因此,Ruby在计算期间最终在内存中有3个数组; Python只需要输入列表和结果列表。

    Python也提供类似的地图理解。

  5. Python支持元组; Ruby没有。在Ruby中,您必须使用数组来模拟元组。

  6. Ruby支持switch / case语句; Python没有。

  7. Ruby支持标准expr ? val1 : val2三元运算符; Python没有。

  8. Ruby仅支持单继承。如果需要模仿多重继承,可以定义模块并使用mix-ins将模块方法拉入类中。 Python支持多继承而不是模块混合。

  9. Python仅支持单行lambda函数。 Ruby块是一种lambda函数,可以是任意大的。因此,Ruby代码通常以比Python代码更实用的方式编写。例如,要在Ruby中循环遍历列表,通常会执行

    collection.each do |value|
      ...
    end
    

    该块的工作方式与传递给collection.each的函数非常相似。如果你在Python中做同样的事情,你必须定义一个命名的内部函数,然后将它传递给集合中的每个方法(如果列表支持这个方法):

    def some_operation(value):
      ...
    
    collection.each(some_operation)
    

    这不是很好。因此,通常在Python中使用以下非功能性方法:

    for value in collection:
      ...
    
  10. 在两种语言之间以安全的方式使用资源是完全不同的。这里的问题是你要分配一些资源(打开文件,获取数据库游标等),对它执行一些任意操作,然后即使发生异常也要以安全的方式关闭它。

    在Ruby中,因为块很容易使用(参见#9),所以通常会将此模式编码为一个方法,该方法需要阻止任意操作在资源上执行。

    在Python中,传递任意动作的函数有点笨拙,因为你必须编写一个命名的内部函数(参见#9)。相反,Python使用with语句来安全地处理资源。有关详细信息,请参阅How do I correctly clean up a Python object?

答案 1 :(得分:27)

我花了几个月的时间学习Python,经过6年的Ruby学习。对于这两种语言,确实没有很好的比较,所以我决定自己编写并自己写一个。现在, 主要关注函数式编程,但是既然你提到了Ruby的inject方法,我猜我们的波长是相同的。

我希望这会有所帮助:The 'ugliness' of Python

有几点会让你朝着正确的方向前进:

  • 您在Ruby中使用的所有函数编程优点都在Python中,而且更加容易。例如,您可以完全按照您的预期映射函数:

    def f(x):
        return x + 1
    
    map(f, [1, 2, 3]) # => [2, 3, 4]
    
  • Python没有像each那样的方法。由于您只使用each作为副作用,因此Python中的等效项是for循环:

    for n in [1, 2, 3]:
        print n
    
  • 当a)你必须一起处理函数和对象集合时b)当你需要使用多个索引进行迭代时,列表理解是很好的。例如,要查找字符串中的所有回文(假设您的函数p()对于回文而言都返回true),您只需要一个列表理解:

    s = 'string-with-palindromes-like-abbalabba'
    l = len(s)
    [s[x:y] for x in range(l) for y in range(x,l+1) if p(s[x:y])]
    

答案 2 :(得分:10)

我的建议:不要试图了解差异。了解如何在Python中解决问题。就像对每个问题都有一个Ruby方法(它非常适用于语言的局限性和优势),有一个Python方法来解决这个问题。它们都不同。为了充分利用每种语言,你真的应该学习语言本身,而不仅仅是从一种语言到另一种语言的“翻译”。

现在,据说,差异将帮助您更快地适应并对Python程序进行1次修改。这对于开始写作来说很好。但是,尝试从其他项目中学习建筑和设计决策背后的原因,而不是语言语义背后的原因......

答案 3 :(得分:8)

我对Ruby知之甚少,但这里有一些关于你提到的事情的要点:

  • nil,表示缺少值的值为None(请注意,您要检查x is Nonex is not None,而不是== } - 或通过强制转换为布尔值,请参阅下一点。)
  • None,零号码(00.00j(复数))和空集合([],{{1} },{},空字符串set()等)被认为是假的,其他一切都被认为是真实的。
  • 对于副作用,("" - )显式循环。为了生成一堆没有副作用的东西,使用列表推导(或者他们的亲戚 - 懒惰的一次迭代器的生成器表达式,所述集合的dict / set comprehensions)。

关于循环:你有for,它在可迭代(!不计数)和for上运行,它可以达到预期效果。由于对迭代器的广泛支持,更加强大。不仅几乎所有可以作为迭代器而不是列表的东西都是迭代器(至少在Python 3中 - 在Python 2中,你有两个并且默认是一个列表,遗憾的是)。有很多用于处理迭代器的工具 - while并行迭代任意数量的迭代,zip为您提供enumerate(在任何可迭代,而不仅仅在列表上),甚至切片abritary(可能是大的或无限的)iterables!我发现这些使许多循环任务变得更加简单。毋庸置疑,它们可以很好地与列表推导,生成器表达式等集成。

答案 4 :(得分:6)

在Ruby中,实例变量和方法是完全不相关的,除非你明确地将它们与attr_accessor或类似的东西联系起来。

在Python中,方法只是一个特殊的属性类:一个是可执行的。

例如:

>>> class foo:
...     x = 5
...     def y(): pass
... 
>>> f = foo()
>>> type(f.x)
<type 'int'>
>>> type(f.y)
<type 'instancemethod'>

这种差异有很多含义,例如,引用f.x指的是方法对象,而不是调用它。另外,正如您所看到的,f.x默认是公共的,而在Ruby中,实例变量默认是私有的。