从Ruby学习python;区别和相似性

Learning Python from Ruby; Differences and Similarities

我很了解鲁比。我相信我现在可能需要学Python。对于同时了解这两个概念的人来说,这两个概念之间有什么相似之处,又有什么不同之处?

我在找一个类似于我为javascripters学习lua所写的初级读物的列表:简单的东西,如空白意义和循环结构;python中的nil的名称,以及什么值被认为是"真实的";使用mapeach的等价物是惯用的还是含糊不清的?你在咕哝吗?

如果我得到了各种各样的答案,我很乐意将它们汇总到社区wiki中。或者你们都可以互相打架,互相抄袭,试图创造出一个真正的综合清单。

编辑:很明显,我的目标是"合适的"和惯用的python。如果有一个相当于inject的python,但是没有人使用它,因为有一种更好/不同的方法来实现迭代列表和在过程中积累结果的共同功能,我想知道您是怎么做的。也许我将用一个公共目标列表来更新这个问题,您如何在Ruby中实现这些目标,并询问在Python中等价于什么。


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

  • Ruby有块,而Python没有。

  • python有函数,ruby没有。在Python中,可以获取任何函数或方法并将其传递给另一个函数。在Ruby中,一切都是一个方法,方法不能直接传递。相反,您必须将它们包装在proc中才能传递它们。

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

  • python有列表理解,非常有表现力。例如,如果你有一个数字列表,你可以写

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

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

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

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

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

  • python支持元组;ruby不支持。在ruby中,必须使用数组来模拟元组。

  • Ruby支持switch/case语句;python不支持。

  • ruby支持标准的expr ? val1 : val2三元运算符;python不支持。

  • Ruby只支持单一继承。如果需要模拟多个继承,可以定义模块并使用mix-in将模块方法拉入类中。python支持多继承而不是模块混合。

  • python只支持单行lambda函数。Ruby块是类/类lambda函数,可以任意大。因此,Ruby代码通常比Python代码更具功能性。例如,要在Ruby中循环一个列表,通常需要

    1
    2
    3
    collection.each do |value|
      ...
    end

    块的工作原理非常类似于传递给collection.each的函数。如果要在python中执行相同的操作,则必须定义一个命名的内部函数,然后将其传递给集合每个方法(如果list支持此方法):

    1
    2
    3
    4
    def some_operation(value):
      ...

    collection.each(some_operation)

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

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

    在Ruby中,由于块很容易使用(请参见9),因此通常将此模式编码为一种方法,该方法需要一个块来对资源执行任意操作。

    在Python中,为任意操作传入函数有点笨拙,因为您必须编写一个命名的内部函数(请参见9)。相反,python使用with语句进行安全的资源处理。看看如何正确地清理一个python对象?了解更多详细信息。


  • 在学习了6年的Ruby之后,我刚刚花了几个月的时间学习了Python。这两种语言真的没有什么好的比较,所以我决定自己动手写一种。现在,它主要涉及函数式编程,但是既然您提到了Ruby的inject方法,我猜我们的波长是相同的。

    我希望这能有所帮助:Python的"丑陋"

    几个能让你朝着正确的方向移动的点:

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

      1
      2
      3
      4
      def f(x):
          return x + 1

      map(f, [1, 2, 3]) # => [2, 3, 4]
    • python没有类似于each的方法。由于您只使用each作为副作用,所以python中的等效项是for循环:

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

      1
      2
      3
      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])]


    我的建议是:不要试图去了解这些差异。了解如何处理Python中的问题。就像对每个问题都有一个Ruby方法(考虑到语言的局限性和优势,这种方法非常有效),对这个问题也有一个Python方法。它们都是不同的。为了从每种语言中获得最好的效果,你真的应该学习语言本身,而不仅仅是从一种语言到另一种语言的"翻译"。

    现在,有了这一点,差异将帮助您更快地适应并对Python程序进行1次修改。这样就可以开始写作了。但是尝试从其他项目中学习架构和设计决策背后的原因,而不是语言语义背后的原因……


    我知道小鲁比,但以下是一些你提到的事情的要点:

    • nil,表示缺少值的值,将是None(注意,您检查它时,如x is Nonex is not None,而不是==,或通过强制布尔值,见下一点)。
    • None、zero-esque数(00.00j、空集合([]{}set()、空字符串""等)被认为是不可靠的,其他都被认为是真实的。
    • 对于副作用,(for循环)。对于生成一组没有副作用的新东西,使用列表理解(或其亲属-惰性一次性迭代器的生成器表达式,所述集合的dict/set理解)。

    关于循环:您有一个for,它在一个不可重复的(!不算在内),还有while,这是你所期望的。由于对迭代器的广泛支持,fromer更加强大。不仅几乎所有可以成为迭代器而不是列表的东西都是迭代器(至少在Python3中——在Python2中,两者都有,而且缺省值是列表,遗憾的是)。使用迭代器的工具有很多——zip并行迭代任意数量的iterables,enumerate给你(index, item)(在任何一个iterables上,而不仅仅是在列表上),甚至是简单的切片(可能是大的或无限的)iterables!我发现这些可以使许多循环任务简单得多。不用说,它们与列表理解、生成器表达式等集成得很好。


    在Ruby中,实例变量和方法是完全不相关的,除非您将它们与attr_访问器或类似的东西显式关联。

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

    例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> class foo:
    ...     x = 5
    ...     def y(): pass
    ...
    >>> f = foo()
    >>> type(f.x)
    <type 'int'>
    >>> type(f.y)
    <type 'instancemethod'>

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