从Ruby学习Python; 异同

Phr*_*ogz 129 ruby python

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

我正在寻找一个类似于我为JavaScripters学习Lua所做的入门的列表:简单的事情,如空白意义和循环结构; nilPython中的名称,以及哪些值被视为"truthy"; 是不是习惯于使用相当于mapeach/或笨拙的 东西 ,那些大概笨拙的常规吗?

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

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

Cli*_*ler 152

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

  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]
    
    Run Code Online (Sandbox Code Playgroud)

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

    values.select {|v| v > 15}.map {|v| v * v}
    
    Run Code Online (Sandbox Code Playgroud)

    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
    
    Run Code Online (Sandbox Code Playgroud)

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

    def some_operation(value):
      ...
    
    collection.each(some_operation)
    
    Run Code Online (Sandbox Code Playgroud)

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

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

    在Ruby中,因为块非常容易使用(参见#9),所以通常将此模式编码为一种方法,该方法为在资源上执行的任意操作取一个块.

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

  • 是的确如此.`val1 if expr else val2`.8.虽然我看到它主要用于mixin式增强. (25认同)
  • #4中的ruby示例不是惯用的.编写`values.map {| v |会更加ruby-ish(和可读)v*v如果v> 15} .compact`.恕我直言,这比你的python例子更具表现力(当然也更清晰). (15认同)
  • 除了以上,使用了!紧凑函数的版本避免了数组的副本:`values.map {| v | v*v如果v> 15} .compact!`.这意味着只有输入列表和结果列表存在于内存中.请参见此处的#4:http://www.igvita.com/2008/07/08/6-optimization-tips-for-ruby-mri/ (10认同)
  • 3. Python 3`nonlocal`修复了这个问题4.Python还为你提供了生成器表达式(类似于列表推导,但是在被要求之前不要计算任何东西 - 将列表推导看作生成器表达式提供给`list`(它需要一个可迭代的)并返回一个包含迭代产生的所有内容的列表 - 在某些情况下这可以节省很多工作量). (2认同)
  • @ClintMiller哇,没有开关/案例?那么,在Python中实现类似功能的建议方法是什么?的if/else/IF? (2认同)
  • @delnan.我应该提到这一点.我只是想说它不支持其他语言中常见的标准三元语法.Python改变了一下. (2认同)
  • @Phrogz对于小案例,如果/ elsif是要走的路.对于更大的案例,构建将案例映射到该案例的函数的地图可能更好.这是Python中有争议的领域之一,也是Guido在他脚下挖掘的地方之一. (2认同)

Dav*_* J. 27

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

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

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

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

    def f(x):
        return x + 1
    
    map(f, [1, 2, 3]) # => [2, 3, 4]
    
    Run Code Online (Sandbox Code Playgroud)
  • Python没有像这样的方法each.由于您仅each用于副作用,因此Python中的等效项是for循环:

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

    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])]
    
    Run Code Online (Sandbox Code Playgroud)

  • `[s [x:y]表示x在范围(l)中y表示范围(x,l + 1),如果p(s [x:y])]` - 这一行表示Python如何难以阅读.当你阅读Ruby代码时,你的眼睛从左向右移动,没有返回.但是要阅读Python代码,你需要左右 - 左 - 右 - 左 - 右...括号,圆括号,圆括号,括号......在Python中你经常需要混合方法和函数.这很疯狂:`E(C(AB()).D())`而不是Ruby的'ABCDE` (10认同)
  • 您似乎不了解方法的工作原理.方法本质上是一个函数,其第一个参数是方法所属类的实例.当你编写`Class.method`时,方法是"unbound",第一个参数应该是`Class`实例; 当你编写`object.method`时,该方法被"绑定"到`Class`的`object`实例.这使您可以选择是否每次使用map(etc)在差异实例上调用方法(传递未绑定的方法),或者保持实例固定并每次传递不同的第二个参数.两者都很有用. (5认同)
  • 叹了口气,我读到了这篇帖子,这证实了我的怀疑:很少有人理解Python中特殊方法的作用和效用.它们非常有用和标准化,并且它们被强调,以避免与它们经常实现的内置命名冲突.没有人真正了解Python正在试图阻止他们的使用. (3认同)
  • 你是对的,我不明白他们是如何工作的.自从发表这篇文章以来,我对它有了更好的认识.谢谢! (2认同)
  • @Nakilon这就是为什么你应该只使用嵌套列表推导来实现非常简单的情况,而不是像上面那样.编写一个可以在字符串中找到所有回文的单行可能是"聪明的",但最好保留给代码高尔夫.对于其他人以后必须阅读的真实代码,您只需编写一些行函数.所以是的,这条线很难读,但那是程序员的错,而不是语言的错. (2认同)

irc*_*ell 10

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

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

  • 我很感激你的建议.我完全同意情绪_(我将其解释为"学习编写惯用语")_.这正是我想要做的.我不是要问_"Ruby的'each`方法的Python名称是什么?"_我问_"如何在Python中正确完成的事情与Ruby不同,它们在哪里做得恰到好处?"_如果Python的'false`实际上是'False`,这对我知道何时何地应该以Rubyesque方式做事,以及何时何地不应该这样做都同样重要. (7认同)
  • @Phrogz:这很公平.我解释你的问题的方式是:*让我们列出差异列表,这样我们就可以改变我们编程的语言*.但这是一个公平的问题.我想我只是错误地解释了你的要求.我会把它留在这里作为参考,但是看看还有什么东西会很有趣...... (2认同)

小智 8

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

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

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

  • 生成器表达很酷.他们为Python提供了一些像Haskell这样的语言的懒惰评估功能. (2认同)

小智 6

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

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

例如:

>>> class foo:
...     x = 5
...     def y(): pass
... 
>>> f = foo()
>>> type(f.x)
<type 'int'>
>>> type(f.y)
<type 'instancemethod'>
Run Code Online (Sandbox Code Playgroud)

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

  • 实际上,我更明确地说:在Python中,方法只是一种特殊的属性,而在Ruby中,属性只是一种特殊的方法.两种语言之间的一些重要对比功能不在于此:Python中的第一类函数和Ruby中的统一访问原则 (2认同)