问题:从Ruby学习Python;异同
我非常了解Ruby。我认为目前可能需要学习Python。对于既了解这两个概念的人,两者之间哪些概念相似,又有什么不同?
我正在寻找与我为《面向JavaScripters的学习Lua》写的入门读物相似的列表:诸如空格含义和循环构造之类的简单内容;nil
Python中的名称,以及哪些值被认为是“真实的”;是惯用的使用相当于map
和each
,或者是咕哝 somethingaboutlistcomprehensions MUMBLE常态?
如果我得到各种各样的答案,我很乐意将它们汇总到社区Wiki中。否则,大家可以互相搏斗,尝试创建一个真正的综合清单。
编辑:明确地说,我的目标是“适当的”和惯用的Python。如果有Python的等价物inject
,但没有人使用它,因为有一种更好/不同的方法来实现迭代列表和沿途累积结果的通用功能,我想知道您的工作方式。也许我会用一个共同的目标列表来更新这个问题,这些目标是如何在Ruby中实现的,并询问在Python中等效的目标。
回答 0
这是我的一些主要区别:
Ruby有块;Python没有。
Python具有功能;Ruby没有。在Python中,您可以采用任何函数或方法并将其传递给另一个函数。在Ruby中,一切都是方法,不能直接传递方法。相反,您必须将它们包装在Proc中才能通过。
Ruby和Python都支持闭包,但是方式不同。在Python中,您可以在另一个函数中定义一个函数。内部函数对外部函数的变量具有读访问权限,但对写函数没有访问权限。在Ruby中,您可以使用块定义闭包。闭包对外部作用域的变量具有完全的读取和写入访问权限。
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还提供了类似的地图理解。
Python支持元组;露比没有 在Ruby中,您必须使用数组来模拟元组。
Ruby支持switch / case语句;Python没有。
Ruby支持标准的expr ? val1 : val2
三元运算符。Python没有。Ruby仅支持单继承。如果您需要模拟多重继承,则可以定义模块并使用混入将模块方法拉入类。Python支持多重继承,而不是模块混合。
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: ...
两种语言之间以安全的方式使用资源是完全不同的。在这里,问题在于您想要分配一些资源(打开文件,获取数据库游标等),对其进行一些任意操作,然后即使发生异常也以安全的方式关闭它。
在Ruby中,由于块非常易于使用(请参阅#9),因此通常将这种模式编码为一种方法,该方法采用块来对资源执行任意操作。
在Python中,为任意动作传递函数会比较麻烦,因为您必须编写一个命名的内部函数(请参阅#9)。相反,Python使用
with
语句来安全地处理资源。请参阅如何正确清理Python对象?更多细节。
回答 1
经过6年的Ruby,我花了几个月的时间学习Python。对于这两种语言,确实没有很好的比较,所以我决定亲自写一个。现在,它是主要关注的函数式编程,但既然你提到了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)需要使用多个索引进行迭代时,列表的理解非常有用。例如,要查找字符串中的所有回文(假设您有一个
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
我的建议:不要尝试去学习差异。了解如何使用Python解决问题。就像有一个针对每种问题的Ruby方法(考虑到语言的局限性和优势,这种方法非常有效),也有一种针对该问题的Python方法。他们都是不同的。为了充分利用每种语言,您确实应该学习语言本身,而不仅仅是学习一种语言到另一种语言的“翻译”。
如此说来,两者之间的区别将帮助您更快地适应和对Python程序进行一次修改。刚开始写作就很好。但是尝试从其他项目中了解架构和设计决策背后的原因,而不是语言语义背后的原因…
回答 3
我几乎不了解Ruby,但是这里有一些关于您提到的内容的要点:
nil
,表示缺少值的值将是None
(请注意,您可以像x is None
或那样检查它x is not None
,而不用==
-或通过强制布尔值检查它,请参阅下一点)。None
零式的数字(0
,0.0
,0j
(复数))和空集([]
,{}
,set()
,空字符串""
,等等)被认为falsy,一切被认为是truthy。- 对于副作用,(
for
-)显式循环。要生成一堆没有副作用的新东西,请使用列表推导(或它们的亲戚-懒惰的一次性迭代器的生成器表达式,所述集合的dict / set推导)。
关于循环:您具有for
,它以可迭代(!不计算在内)进行操作,而while
,它可以实现预期的效果。得益于对迭代器的广泛支持,源代码的功能要强大得多。不仅几乎所有可以成为迭代器而不是列表的东西都是迭代器(至少在Python 3中-在Python 2中,您同时拥有了这两个,默认情况下,列表是一个列表)。有很多使用迭代器的工具- zip
并行迭代任意数量的可迭代对象,enumerate
为您(index, item)
(在任何可迭代对象上,不仅在列表中)提供切片,甚至切片可迭代对象(可能很大或无限)!我发现这些使许多循环任务变得更加简单。不用说,它们可以很好地与列表推导,生成器表达式等集成。
回答 4
在Ruby中,实例变量和方法是完全不相关的,除非您将它们与attr_accessor或类似的东西显式关联。
在Python中,方法只是一种特殊的属性类:一种可执行的属性。
因此,例如:
>>> class foo:
... x = 5
... def y(): pass
...
>>> f = foo()
>>> type(f.x)
<type 'int'>
>>> type(f.y)
<type 'instancemethod'>
这种差异具有很多含义,例如,引用fx引用方法对象而不是调用它。另外,如您所见,fx默认情况下是公共的,而在Ruby中,实例变量默认情况下是私有的。