我很了解鲁比。我相信我现在可能需要学Python。对于同时了解这两个概念的人来说,这两个概念之间有什么相似之处,又有什么不同之处?
我在找一个类似于我为javascripters学习lua所写的初级读物的列表:简单的东西,如空白意义和循环结构;python中的nil的名称,以及什么值被认为是"真实的";使用map和each的等价物是惯用的还是含糊不清的?你在咕哝吗?
如果我得到了各种各样的答案,我很乐意将它们汇总到社区wiki中。或者你们都可以互相打架,互相抄袭,试图创造出一个真正的综合清单。
编辑:很明显,我的目标是"合适的"和惯用的python。如果有一个相当于inject的python,但是没有人使用它,因为有一种更好/不同的方法来实现迭代列表和在过程中积累结果的共同功能,我想知道您是怎么做的。也许我将用一个公共目标列表来更新这个问题,您如何在Ruby中实现这些目标,并询问在Python中等价于什么。
- 我唯一看到的是c2.com/cgi/wiki?我真的不喜欢自己和缩进,但我已经习惯了:)
- 相关:stackoverflow.com/question s/1113611/…(我不太确定它是否是重复的,因为这个问题要求的是没有等价物的东西)。
- @saif上次我检查的时候,讨论中有很多过时的坏例子。当你不听从ircmaxell的建议时,建议a=[];0.upto(2){|i|0.upto(2){|j|a<<[i,j] if i!=j}}作为一个红宝石等价于[(x,y) for x in xrange(3) for y in xrange(3) if x != y](然后去掉所有空白并称之为改进),这几乎是你冒的风险。
- 我注意到了,但这可能是一个很好的起点,我现在在高级项目中使用python,我花了一段时间来适应这种风格。
- @我强烈反对。我在问"语言之间有什么相同,有什么不同?"如下面的许多答案所示,有非常清楚和有用的答案。
- 这是一个很好的讨论:书签!
- @我明白这一点,使这个问题无法回答。
- 这个问题适合程序员SE吗?
- @phrongz-为了回应我在你发布的元主题上所说的话,这个问题的问题是问题空间太大了——一个主题对于一个问题来说太大了。这两种语言有数千种不同之处。
- 投票重新开始。下面的一些答案表明这个问题是可以回答的,并且在将来是有用的。
- 我既不使用Ruby也不使用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对象?了解更多详细信息。
- 三。python 3 nonlocal修复了这4个问题。python还为您提供了生成器表达式(类似于列表理解,但在被要求之前不要计算任何内容-将列表理解视为发送给list的生成器表达式(它接受一个iterable并返回一个包含iterable生成的所有内容的列表),这在某些情况下可以节省很多工作。
- 7。是的。val1 if expr else val2。8。虽然我看到它主要用于混合样式的增强。
- @ClintMiller哇哦,没有开关/箱子?那么,在Python中实现类似功能的建议方法是什么?如果/如果/如果?
- @德尔南。我本该提到的。我只是想说它不支持其他语言中常见的标准三元语法。python稍微改变了一下。
- 在python中,所有语句都是表达式(如上面的if/else所示),这是一个共性吗?
- @对于小的情况,可以使用phrogz,if/elsif。对于更大的情况,构建一个映射案例到该案例函数的映射可能更好。这是Python中有争议的领域之一,也是guido挖到脚的地方。
- +1对于这个伟大的概述。@Delnan:+1用于提及生成器表达式
- @不,python通常将表达式和语句分开。表达式中的条件"operator",恰好重用条件语句中的关键字。
- @phrogz all语句不是Python中的表达式。例如,for循环不产生值。赋值也不是表达式。例如,在Ruby中,您可以编写(x=5)>3,计算结果为true。在python中,这不是有效的语句。
- @phrogz:如果在python中需要switch/case,可以使用字典。
- 彻底的回答。9。我同意,Ruby块更容易编写函数代码(因为您不必编写列表/生成器理解+单独的函数)。但是在这个例子中,您不应该使用"collection.each",这是不起作用的!例如,更好的"collection.map"。11。python通过生成器支持惰性(这也不完美,您会失去持久性)。
- 7。(val1,val2)【expr】做类似的事情,人类更容易阅读。
- 您在4中的Ruby示例不是惯用的。写values.map{|v| v*v if v > 15}.compact会更像红宝石色(并且可读)。imho,这比您的Python示例更具表现力(当然也更清晰)。
- 除上述外,使用!compact函数的版本避免了数组的副本:values.map{|v| v*v if v > 15}.compact!。这意味着内存中只存在输入列表和结果列表。见4这里:igvita.com/2008/07/08/6-optimization-tips-for-ruby-mri
- [关于lambda一行程序]python的表达式语法(条件的三元运算符,循环的列表理解)足够强大,能够将任何函数重写为lambda(尽管异常和其他副作用可能难以转换为函数样式)-它们是图灵完备的。因此,完全可以在lambdas中进行编程,但这并不容易、易读、简单。
- 2。Ruby lambda如何不起作用?三。在Ruby中,您可以在lambda中定义一个lambda,不是吗?
- 我一看到这4个。我希望会有像@sml's.:d这样的评论。
在学习了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中特殊方法的作用和实用性。它们是非常有用和标准化的,它们被强调为这样可以避免与它们经常实现的内置设备发生命名冲突。没有一个真正了解Python的人试图阻止他们的使用。
- 你似乎不明白方法是如何工作的。方法本质上是一个函数,其第一个参数是该方法所属类的实例。写Class.method时,方法是"unbound",第一个参数应该是Class实例;写object.method时,方法是"bound"到Class的object实例。这允许您选择是每次使用map(etc)调用差分实例上的方法(传递未绑定的方法),还是保持实例固定并每次传递不同的第二个参数。两者都是有用的。
- 你说得对,我不明白他们是怎么工作的。自从发表这篇文章以来,我对它有了更好的理解。谢谢!
- ▼显示 for x in range(l) for y in range(x,l+1) if p(s[x:y])]-这一行显示了Python的难读性。当你读到Ruby代码时,你的眼睛会从左向右移动,不会返回。但要读取python代码,您需要向左、右、左、右……还有括号,括号,括号,括号…同样,在Python中,您经常需要混合方法和函数。这太疯狂了:E(C(A.B()).D())而不是Ruby的A.B.C.D.E
- @Nakilon这就是为什么您应该只对非常简单的情况使用嵌套列表理解,而不是像上面那样。写一个能在字符串中找到所有回文的一行程序也许是"聪明的",但它最好是为代码高尔夫保留的。对于其他人稍后必须阅读的真正代码,您只需编写几行函数即可。所以是的,这一行很难读,但这是程序员的错,而不是语言的错。
- @拉菲凯特勒哇,这篇文章真糟糕。map(str.capitalize, [])不是深层的python。
- 嗨,迈尔斯,听到你这么想我很难过。python是我所知道的唯一一种与"self/this"有关系的语言,它允许这种事情发生,所以它让我吃惊。显然,您可以在javascript中执行这种操作,但只有在重新绑定this之后,我第一次看到一个实例方法映射到另一个没有这种重新绑定的对象时,我才感到困惑。
- @ DavidJ。fwiw-lua以类似于python的方式提供面向对象的编程:定义明确接收第一个参数的函数,该参数是要操作的self。参见phrogz.net/lua/learninglua_scope.html
我的建议是:不要试图去了解这些差异。了解如何处理Python中的问题。就像对每个问题都有一个Ruby方法(考虑到语言的局限性和优势,这种方法非常有效),对这个问题也有一个Python方法。它们都是不同的。为了从每种语言中获得最好的效果,你真的应该学习语言本身,而不仅仅是从一种语言到另一种语言的"翻译"。
现在,有了这一点,差异将帮助您更快地适应并对Python程序进行1次修改。这样就可以开始写作了。但是尝试从其他项目中学习架构和设计决策背后的原因,而不是语言语义背后的原因……
- 谢谢你的建议。我完全同意这种观点(我将其解释为"学会编程惯用的python")。这正是我想做的。我不是在问"Ruby的each方法的python名称是什么?"我在问"在Python中如何正确地完成与Ruby不同的事情,以及在哪里正确地完成了相同的事情?"如果python的false实际上是false,那么知道我应该在何时何地以一种鲁莽的方式做事情,以及不应该在何时何地做事情,这一点同样重要。
- @弗罗兹:那是公平的。我解释你的问题的方式是:让我们列出不同之处,这样我们就可以改变我们正在编程的语言。但这是一个公平的问题。我想我只是误解了你的要求。我将把这个留在这里作为参考,但看看还有什么会很有趣…
- 我同时学习了Python和Ruby,在Web应用程序开发中,我看到了更多的相似之处而不是不同之处。
我知道小鲁比,但以下是一些你提到的事情的要点:
- nil,表示缺少值的值,将是None(注意,您检查它时,如x is None或x is not None,而不是==,或通过强制布尔值,见下一点)。
- None、zero-esque数(0、0.0、0j、空集合([]、{}、set()、空字符串""等)被认为是不可靠的,其他都被认为是真实的。
- 对于副作用,(for循环)。对于生成一组没有副作用的新东西,使用列表理解(或其亲属-惰性一次性迭代器的生成器表达式,所述集合的dict/set理解)。
关于循环:您有一个for,它在一个不可重复的(!不算在内),还有while,这是你所期望的。由于对迭代器的广泛支持,fromer更加强大。不仅几乎所有可以成为迭代器而不是列表的东西都是迭代器(至少在Python3中——在Python2中,两者都有,而且缺省值是列表,遗憾的是)。使用迭代器的工具有很多——zip并行迭代任意数量的iterables,enumerate给你(index, item)(在任何一个iterables上,而不仅仅是在列表上),甚至是简单的切片(可能是大的或无限的)iterables!我发现这些可以使许多循环任务简单得多。不用说,它们与列表理解、生成器表达式等集成得很好。
- 生成器表达式很酷。它们给了Python一些像Haskell这样的语言的延迟评估功能。
- @ Clint:是的。而且,全功率发电机的性能甚至更高(尽管简单的情况下不需要,而这些情况恰好占大多数)。
- 你为什么要和x is None或x is not None核对?我总是和x == None和x != None核对。
- @约翰:如果x以一种愚蠢的方式定义__eq__,它可能会给出一个假阳性。如果__eq__编程不够仔细,在给定某些值(如None时,它可能崩溃(如AttributeError)。相反,is不能被重写——它总是比较对象标识,这是检查单例的正确方法(最健壮、最简单和最干净)。
- (不想争论,只想学习)x会怎样超载__eq__?只有当__eq__未被覆盖时才会发生这种情况吗?
- @约翰:见docs.python.org/reference/datamodel.html special method name&zwnj;&8203;s。示例:class Spam(object): \indent def __eq__(self, other): return self.x == other.x \dedent \dedent。我认为__eq__的默认实现比较了身份(至少在class Ham(object): pass之后Ham() != Ham())。
- 最低限度。我找不到任何能解释如何从新手到高级的东西。我发现的每一个教程甚至都不能解释课程,所以我的学习进度很慢,只需在这里提问,并尝试在我的头上阅读代码英里数。谢谢你的帮助。
- "约翰。""x is none"是完全惯用的方法。python.net/~goodger/projects/pycon/2007/惯用/讲义.ht&zwnj;&8203;ml
- @托克兰:好地方!谢谢!
在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中,实例变量默认情况下是私有的。
- 实际上,我更明确地说:在Python中,方法只是一种特殊的属性,而在Ruby中,属性只是一种特殊的方法。这两种语言之间的一些重要的对比特性可以归结为:Python中的第一类函数和Ruby中的统一访问原则。