从Ruby学习Python; 异同

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

我正在寻找一个类似于我写给学习Lua for JavaScripters的入门的列表:简单的东西,比如空白的意义和循环结构; Python中nil的名称,以及什么值被认为是“真理”; 用mapeach map的等价物,还是嘟嘟 something something地 咕咕 the the?

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

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

以下是我的一些关键区别:

  1. ruby有块; Python不。

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

  3. Ruby和Python都支持闭包,但方式不同。 在Python中,您可以在另一个函数中定义一个函数。 内部函数具有对来自外部函数的variables的读取权限,但不具有写入权限。 在Ruby中,你使用块来定义闭包。 闭包拥有对外部variables的完全读写访问权限。

  4. Python有列表parsing,这是很有performance力的。 例如,如果你有一个数字列表,你可以写

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

    得到大于15的所有值的正方形的新列表。在Ruby中,你必须写下以下内容:

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

    Ruby代码感觉不够紧凑。 因为它首先将值数组转换为包含大于15的值的较短的中间数组,所以它也不是那么高效。然后,它将采用中间数组并生成包含中间体平方的最终数组。 中间数组然后被抛出。 所以,在计算过程中,Ruby最终会在内存中存储3个数组; Python只需要input列表和结果列表。

    Python也提供类似的地图parsing。

  5. Python支持元组; Ruby不会。 在Ruby中,你必须使用数组来模拟元组。

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

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

  8. Ruby仅支持单一的inheritance。 如果您需要模仿多重inheritance,则可以定义模块并使用混合将模块方法拉入类中。 Python支持多重inheritance,而不是模块混合。

  9. Python只支持单行lambda函数。 Ruby块,这种types的lambda函数,可以是任意大的。 因此,Ruby代码通常是以比Python代码更实用的风格编写的。 例如,要在Ruby中循环列表,通常是这样

     collection.each do |value| ... end 

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

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

    这不stream通非常好。 因此,Python中通常会使用以下非function方法:

     for value in collection: ... 
  10. 这两种语言在安全使用资源方面有很大不同。 在这里,问题是你想分配一些资源(打开文件,获取数据库游标等),对其执行一些任意的操作,然后以安全的方式closures它,即使发生exception。

    在Ruby中,由于块非常易于使用(请参见#9),因此通常将此模式编码为一种方法,该方法将任意操作的块用于资源上。

    在Python中,由于必须编写一个命名的内部函数(参见#9),因此为任意操作传递一个函数会有点笨拙。 相反,Python使用with语句来进行安全的资源处理。 请参阅如何正确清理Python对象? 更多细节。

我花了几个月的时间学习了6年的Ruby。 这两种语言真的没有很好的比较,所以我决定自己写一个。 现在,它主要关注函数式编程,但是由于您提到了Ruby的inject方法,我猜测我们处于同一个波长。

我希望这有助于: 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)需要使用多个索引进行迭代时,列表parsing是非常好的。 例如,要find一个string中的所有回文(假设你有一个函数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])] 

我的build议:不要试图了解差异。 学习如何在Python中处理这个问题。 就像每个问题都有一个Ruby方法(这个方法很好的解决了这个语言的限制和优势),这个问题有一个Python方法。 他们是不同的。 为了充分利用每种语言,你应该学习语言本身,而不仅仅是从一个到另一个的“翻译”。

现在,有了这个说法,这个差异将会帮助你更快地适应Python程序的修改。 对于一开始写作来说,这很好。 但是尝试从其他项目中学习为什么在架构和devise决策背后,而不是语言语义的背后。

我知道小ruby,但这里有一些关于你提到的事情的要点:

  • nil ,表示缺less值的值将是None (请注意,您检查它是否像x is None或者x is not None ,不是用== ,或者通过强制转换为boolean,见下一点)。
  • None ,零度数字( 0j (复数))和空集合( []{}set() ,空string""等)被认为是虚假的,其他一切都被认为是真实的。
  • 对于副作用,( for – )显式循环。 为了生成一个没有副作用的新东西,使用列表推导(或其亲属 – 生成器expression式用于懒惰一次性迭代器,对所述集合的dict / setparsing)。

关于循环:你需要的for ,它运行在一个可迭代的(!不计数)和while ,这是你所期望的。 由于对迭代器的广泛支持,前者的function要强大得多。 不仅几乎所有可以作为迭代器而不是列表的东西都是一个迭代器(至less在Python 3中 – 在Python 2中,你有两个,默认情况下是一个列表,不幸的是)。 使用迭代器的工具很多–zim并行地迭代任意数量的迭代器, enumerate给你(index, item) (在任何迭代器上,而不仅仅是在列表上),甚至可以切割abritary(可能是大的或无限的)迭代器! 我发现这些使许多循环任务变得更简单。 毋庸置疑,它们与列表理解,生成器expression式等结合得很好。

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

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

举个例子:

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

这个区别有很多含义,例如,引用fx指的是方法对象,而不是调用它。 另外,正如你所看到的,fx默认是公共的,而在Ruby中,实例variables默认是私有的。