答案 0 :(得分:34)
Ruby具有 blocks 的概念,它们基本上是围绕一段代码的语法糖;它们是一种创建闭包并将它们传递给另一种可能使用或不使用该块的方法的方法。稍后可以通过yield
语句调用块。
例如,each
上Array
方法的简单定义可能类似于:
class Array
def each
for i in self
yield(i) # If a block has been passed, control will be passed here.
end
end
end
然后你可以像这样调用它:
# Add five to each element.
[1, 2, 3, 4].each{ |e| puts e + 5 }
> [6, 7, 8, 9]
Python有匿名函数/闭包/ lambdas,但由于缺少一些有用的语法糖,所以它没有块。但是,至少有一种方法可以以临时方式获得它。例如,请参阅here。
答案 1 :(得分:28)
函数是Python中的第一类变量。您可以声明一个函数,将其作为对象传递,然后覆盖它:
def func(): print "hello"
def another_func(f): f()
another_func(func)
def func2(): print "goodbye"
func = func2
这是现代脚本语言的基本特征。 JavaScript和Lua也这样做。 Ruby不会以这种方式处理函数;命名函数会调用它。
当然,有很多方法可以在Ruby中做这些事情,但它们不是一流的操作。例如,您可以使用Proc.new包装函数将其视为变量 - 但它不再是函数;它是一个带有“调用”方法的对象。
Ruby函数不是第一类对象。函数必须包装在一个对象中以传递它们;生成的对象不能像函数一样对待。功能不能以一流的方式分配;相反,必须调用其容器对象中的函数来修改它们。
def func; p "Hello" end
def another_func(f); method(f)[] end
another_func(:func) # => "Hello"
def func2; print "Goodbye!"
self.class.send(:define_method, :func, method(:func2))
func # => "Goodbye!"
method(:func).owner # => Object
func # => "Goodbye!"
self.func # => "Goodbye!"
答案 2 :(得分:26)
最终所有的答案在某种程度上都是主观的,到目前为止发布的答案几乎证明你不能指出任何一种在另一种语言中不可行的功能同样不错(如果不是类似的方式,因为两种语言都非常简洁和富有表现力。
我喜欢Python的语法。但是,你必须比语法更深入地挖掘Ruby的真正美。 Ruby的一致性具有禅宗般的美感。虽然没有一个简单的例子可以完全解释这一点,但我会试着在这里提出一个解释我的意思。
反转此字符串中的字词:
sentence = "backwards is sentence This"
当你考虑如何做到这一点时,你会做以下事情:
在Ruby中,你会这样做:
sentence.split.reverse.join ' '
正如你想的那样,在同一个序列中,一个方法一个接一个地调用。
在python中,它看起来更像是这样:
" ".join(reversed(sentence.split()))
这并不难理解,但它并没有完全相同的流程。主语(句子)埋在中间。这些操作是函数和对象方法的混合。这是一个简单的例子,但是当真正使用和理解Ruby时,会发现许多不同的例子,特别是在非平凡的任务上。
答案 3 :(得分:18)
您只能从Python中导入模块中的特定功能。在Ruby中,您可以导入整个方法列表。你可以在Ruby中“取消”它们,但它并不是它的全部内容。
编辑:
让我们来看看这个Ruby模块:
module Whatever
def method1
end
def method2
end
end
如果您在代码中包含它:
include Whatever
您会看到 method1 和 method2 已添加到您的命名空间中。您不能仅导入 method1 。您可以同时导入它们,也可以根本不导入它们。在Python中,您只能导入您选择的方法。如果这个名称可能会被称为选择性导入?
答案 4 :(得分:18)
例如,Ruby:
>> PI = 3.14
=> 3.14
>> PI += 1
(irb):2: warning: already initialized constant PI
=> 4.14
的Python:
>>> PI = 3.14
>>> PI += 1
>>> PI
4.1400000000000006
答案 5 :(得分:16)
来自Ruby的website:
相似 与Python一样,在Ruby中......
- 有一个互动提示(称为irb)。
- 您可以在命令行上阅读文档(使用ri命令而不是pydoc)。
- 没有特殊的行终止符(通常的换行符除外)。
- 字符串文字可以跨越多行,如Python的三引号字符串。
- 括号用于列表,括号用于dicts(在Ruby中称为“哈希”)。
- Arrays的工作方式相同(添加它们会生成一个长数组,但是像
a3 = [ a1, a2 ]
那样组合它们会为你提供一个数组数组。)- 强烈动态地输入对象。
- 一切都是对象,变量只是对象的引用。
- 虽然关键字略有不同,但例外情况大致相同。
- 你有嵌入式doc工具(Ruby的名字叫做rdoc)。
的差异 与Python不同,在Ruby中......
- 字符串是可变的。
- 您可以创建常量(您不打算更改其值的变量)。
- 有一些强制执行的案例约定(例如,类名以大写字母开头,变量以小写字母开头)。
- 只有一种列表容器(一个数组),它是可变的。
- 双引号字符串允许转义序列(如\ t)和特殊的“表达式替换”语法(允许您将Ruby表达式的结果直接插入到其他字符串中,而无需“添加”+“字符串”+“一起”)。单引号字符串就像Python的r“原始字符串”。
- 没有“新风格”和“旧风格”类。只是一种。
- 您永远不会直接访问属性。使用Ruby,它是所有方法调用。
- 方法调用的括号通常是可选的。
- 有公共,私有和受保护来强制访问,而不是Python的
_voluntary_ underscore __convention__
。- 使用“mixin's”代替多重继承。
- 您可以添加或修改内置类的方法。这两种语言都可以让你在任何时候打开和修改类,但是Python会阻止修改内置函数 - Ruby不会。
- 你有真假,而不是真假(和零而不是无)。
- 当测试真相时,只有false和nil评估为假值。其他一切都是真的(包括0,0.0,“”和[])。
- 这是elsif而不是elif。
- 需要而不是导入。否则,用法是相同的。
- 关于事物上方行(而不是下面的文档字符串)的通常风格的注释用于生成文档。
- 有许多快捷方式,虽然可以让你记住更多,但你很快就会学到。他们倾向于让Ruby变得有趣并且非常高效。
答案 6 :(得分:12)
我想建议一个原始问题的变体,“Ruby有什么不具备Python,反之亦然?”承认这个令人失望的答案,“嗯,你能用Ruby或Python做些什么,而Intercal无法做到这一点?”没有任何东西,因为Python和Ruby都是坐在图灵近似宝座上的庞大王室的一部分。
但是这个怎么样:
在Python中可以优雅地完成哪些工作,而这些优秀和良好的工程设计无法在Ruby中完成,反之亦然?
这可能比仅仅进行功能比较更有趣。
答案 7 :(得分:12)
Ruby比Python更具有脚本语言功能。在此上下文中的脚本语言意味着在shell脚本和一般文本操作中用于“粘合代码”。
这些主要与Perl共享。一流的内置正则表达式,$ -Variables,有用的命令行选项,如Perl(-a,-e)等。
与其简洁而又灵巧的语法一起,它非常适合这类任务。
Python对我来说更像是一种动态类型的商业语言,它非常容易学习并且语法清晰。不像Ruby那样酷“但很整洁”。 Python对我来说是对其他lib的大量绑定。绑定到Qt和其他GUI库,许多游戏支持库和和。 Ruby少得多。虽然使用很多绑定,例如数据库质量很好我发现在Python中更好地支持利基库,即使对于同一个库也存在Ruby绑定。
所以,我会说这两种语言都有它的用途,它的任务是定义使用哪种语言。两者都很容易学习。我并排使用它们。 Ruby for scripting和Python for stand-alone apps。
答案 8 :(得分:12)
我不认为“Ruby有X而Python没有,而Python有Y而Ruby没有”是最有用的方式来看待它。它们是非常相似的语言,具有许多共享能力。
在很大程度上,差异在于语言的优雅和可读性。使用你提出的一个例子,理论上它们都有lambdas,但Python程序员倾向于避免它们,并且使用它们构造的构造看起来不像Ruby那样可读或惯用。所以在Python中,一个优秀的程序员会想要采用不同的方法来解决问题而不是Ruby,只是因为它实际上 是更好的方法。
答案 9 :(得分:11)
答案 10 :(得分:11)
基础设施方面的更多内容:
与Ruby相比,Python与C ++(通过诸如Boost.Python,SIP和Py++之类的东西)有更好的集成,其中的选项似乎是直接写入Ruby解释器API(当然,你也可以用Python做,但在这两种情况下这样做都是低级别,单调乏味且容易出错)或使用SWIG(虽然它可以工作,如果你想支持它肯定很棒许多语言,如果你特意想要绑定C ++,就不如Boost.Python或SIP那么好。
Python有许多Web应用程序环境(Django,Pylons / Turbogears,web.py,可能至少有六个其他),而Ruby(有效)有一个:Rails。 (其他Ruby Web框架确实存在,但似乎很难对Rails产生过大的影响)。这个方面好还是坏?很难说,也许很主观;我可以很容易地想象出Python情况更好以及Ruby情况更好的论点。
在文化方面,Python和Ruby社区似乎有所不同,但我只能暗示这一点,因为我没有那么多与Ruby社区交互的经验。我主要是希望那些对两者都有很多经验的人可以放大(或拒绝)这种说法。
答案 11 :(得分:11)
Python有一个用于list-comprehenions和generator的显式内置语法,而在Ruby中你可以使用map和code blocks。
比较
list = [ x*x for x in range(1, 10) ]
到
res = (1..10).map{ |x| x*x }
答案 12 :(得分:11)
“以大写字母开头的变量变为常量且无法修改”
错误。他们可以。
如果你这样做,你只会收到警告。
答案 13 :(得分:9)
其他一些来自:
http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/to-ruby-from-python/
(如果因为该页面已更新,我在Ruby方面发生了任何错误或任何改变,有人可以自由编辑......)
字符串在Ruby中是可变的,而不是在Python中(新的字符串由“更改”创建)。
Ruby有一些强制执行的案例约定,Python没有。
Python有列表和元组(不可变列表)。 Ruby有与Python列表对应的数组,但没有不可变的变体。
在Python中,您可以直接访问对象属性。在Ruby中,它总是通过方法。
在Ruby中,方法调用的括号通常是可选的,但在Python中则不行。
Ruby具有public,private和protected来强制访问,而不是Python的使用下划线和名称修改的约定。
Python有多重继承。 Ruby有“mixins。”
另一个非常相关的链接:
http://c2.com/cgi/wiki?PythonVsRuby
其中特别链接到Alex Martelli的另一个好人,他也在SO上发布了很多很棒的东西:
http://groups.google.com/group/comp.lang.python/msg/028422d707512283
答案 14 :(得分:8)
我不确定这一点,所以我先把它作为答案添加。
这意味着您可以调用类似theobject.themethod()
或TheClass.themethod(anobject)
的方法。
编辑:虽然方法和函数之间的区别在Python中很小,而在Python 3中不存在,但它在Ruby中也不存在,仅仅因为Ruby没有函数。定义函数时,实际上是在Object上定义方法。
但你仍然不能采用一个类的方法并将其作为一个函数调用,你必须将它重新绑定到你想要调用的对象上,这更加困难。
答案 15 :(得分:7)
我想提一下Python描述符API,它允许一个自定义对象到属性的“通信”。还值得注意的是,在Python中,可以通过覆盖通过__getattribute__
方法的默认实现给出的默认值来自由地实现替代协议。
让我提供有关上述内容的更多细节。
描述符是具有__get__
,__set__
和/或__delete__
方法的常规类。
当口译员遇到anObj.anAttr
之类的内容时,会执行以下操作:
__getattribute__
anObj
方法被调用__getattribute__
从类dict __get__
,__set__
或__delete__
可调用对象如前所述,这是默认行为。可以通过重新实现__getattribute__
来自由更改协议。
这种技术比装饰者更强大。
答案 16 :(得分:6)
Ruby使用callcc
内置了持续支持。
因此,你可以实现像amb-operator
这样的很酷的东西答案 17 :(得分:6)
在这个阶段,Python仍然有更好的unicode支持
答案 18 :(得分:5)
Python有文档字符串,ruby没有...或者如果没有,它们就像在python中一样容易访问。
聚苯乙烯。如果我错了,请多好,留下一个例子?我有一个解决方法,我可以非常轻松地monkeypatch到类,但我想在“本地方式”有一个docstring类型的功能。
答案 19 :(得分:5)
我的python生锈了,所以其中一些可能是在python中,我只是不记得/从未学习过,但这里是我想到的前几个:
Ruby处理完全不同的空白。对于初学者,您不需要缩进任何内容(这意味着如果使用4个空格或1个选项卡则无关紧要)。它还可以进行智能线连续,因此以下内容有效:
def foo(bar,
cow)
基本上,如果你以一个操作员结束,它会弄清楚发生了什么。
Ruby有mixins,可以扩展实例而不是完整的类:
module Humor
def tickle
"hee, hee!"
end
end
a = "Grouchy"
a.extend Humor
a.tickle » "hee, hee!"
我不确定这是否与生成器相同,但是从Ruby 1.9 ruby作为枚举,所以
>> enum = (1..4).to_enum
=> #<Enumerator:0x1344a8>
参考:http://blog.nuclearsquid.com/writings/ruby-1-9-what-s-new-what-s-changed
Ruby中支持其中列出的两个项目,但您不能跳过这样的默认值。 你可以按顺序
def foo(a, b=2, c=3)
puts "#{a}, #{b}, #{c}"
end
foo(1,3) >> 1, 3, 3
foo(1,c=5) >> 1, 5, 3
c >> 5
请注意,c = 5实际上将调用范围中的变量c赋值为5,并将参数b设置为值5.
或者您可以使用哈希来解决第二个问题
def foo(a, others)
others[:b] = 2 unless others.include?(:b)
others[:c] = 3 unless others.include?(:c)
puts "#{a}, #{others[:b]}, #{others[:c]}"
end
foo(1,:b=>3) >> 1, 3, 3
foo(1,:c=>5) >> 1, 2, 5
参考:实用的Progammer Ruby指南
答案 20 :(得分:5)
您可以在Ruby和Python中的类定义中包含代码。但是,在Ruby中,您可以引用类(self)。在Python中,您没有对该类的引用,因为该类尚未定义。
一个例子:
class Kaka
puts self
end
自我在这种情况下是类,这段代码将打印出“卡卡”。无法打印出类名或以其他方式从Python中的类定义主体访问该类。
答案 21 :(得分:5)
Ruby在命令行中对输入文件('-n'标志)进行逐行循环,因此可以像AWK一样使用它。这个Ruby单行:
ruby -ne 'END {puts $.}'
将计算像AWK单行的行:
awk 'END{print NR}'
Ruby通过Perl获得了这一功能,Perl将其作为一种使用Perl获取系统管理员的方式,而不必改变他们的工作方式。
答案 22 :(得分:5)
Ruby有sigils和twigils,Python没有。
编辑:我忘记了一个非常重要的事情(毕竟,之前只是为了点燃一点:-p):
Python有一个JIT编译器(Psyco),一种用于编写更快代码(Pyrex)的低级语言,以及添加内联C ++代码(Weave)的能力。
答案 23 :(得分:4)
语法不是一件小事,它对我们的思考方式有直接影响。它还对我们为我们使用的系统创建的规则产生直接影响。作为一个例子,由于我们编写数学方程式或句子的方式,我们有操作的顺序。数学的标准符号允许人们以不同的方式阅读它,并根据相同的等式得出不同的答案。如果我们使用了前缀或后缀表示法,我们就会创建规则来区分要操作的数字,而不是只有计算值的顺序规则。
标准符号表明我们正在讨论的数字是什么,同时使得计算它们的顺序模糊不清。前缀和后缀表示法使得计算简单的顺序同时使数字不明确。如果它不是由语法空白引起的困难,Python已经有多行lambdas。 (建议确实可以在不必添加显式块分隔符的情况下关闭此类事件。)
如果条件 false ,使用Ruby中的unless语句比使用Ruby中语义等效的“if-not”构造更容易编写条件,我觉得更容易编写条件。或其他语言。如果人们今天使用的大多数语言在权力上是相同的,那么每种语言的语法如何被认为是微不足道的呢?在诸如块和继承机制等特定功能之后,语法是语言中最重要的部分,几乎不是一种肤浅的东西。
我们归结为语法的美的审美品质是多么肤浅。美学与我们的认知如何运作无关,语法也是如此。
答案 24 :(得分:3)
很惊讶没有提到红宝石的“方法缺失”机制。我将举例说明Rails中的find_by _...方法,作为该语言功能的一个例子。我的猜测是类似的东西可以在Python中实现,但据我所知,它本身并不存在。
答案 25 :(得分:3)
Paul Graham的Accumulator Generator问题证明了Python和Ruby之间lambda的另一个区别。转载于此:
写一个函数foo,它取一个数字n并返回一个带数字i的函数,并返回n递增i。 注意:(a)该数字,而不是整数,(b)增加的数字,而不是加号。
在Ruby中,你可以这样做:
def foo(n)
lambda {|i| n += i }
end
在Python中,您将创建一个对象来保存n:
的状态class foo(object):
def __init__(self, n):
self.n = n
def __call__(self, i):
self.n += i
return self.n
有些人可能更喜欢显式Python方法,因为它在概念上更清晰,即使它更冗长。你可以像其他任何东西一样存储状态。你只需要围绕可调用对象的想法。但是无论采用哪种方式都是美学上的,它确实表明了一个方面,其中Ruby lambdas是比Python更强大的构造。
答案 26 :(得分:3)
python命名了可选参数
def func(a, b=2, c=3):
print a, b, c
>>> func(1)
1 2 3
>>> func(1, c=4)
1 2 4
AFAIK Ruby只定位参数,因为函数声明中的b = 2是一个总是追加的符号。
答案 27 :(得分:2)
http://c2.com/cgi/wiki?PythonVsRuby
http://c2.com/cgi/wiki?SwitchedFromPythonToRuby
http://c2.com/cgi/wiki?SwitchedFromRubyToPython
http://c2.com/cgi/wiki?UsingPythonDontNeedRuby
http://c2.com/cgi/wiki?UsingRubyDontNeedPython
答案 28 :(得分:2)
在Ruby中,导入文件时 要求,所有定义的东西 该文件将最终出现在您的全局中 命名空间。
使用Cargo,您可以“需要库而不会使命名空间混乱”。
# foo-1.0.0.rb
class Foo
VERSION = "1.0.0"
end
# foo-2.0.0.rb
class Foo
VERSION = "2.0.0"
end
>> Foo1 = import("foo-1.0.0") >> Foo2 = import("foo-2.0.0") >> Foo1::VERSION => "1.0.0" >> Foo2::VERSION => "2.0.0"
答案 29 :(得分:2)
Ruby有嵌入式文档:
=begin
You could use rdoc to generate man pages from this documentation
=end
答案 30 :(得分:1)
我喜欢Ruby和Python方法调用操作方式的根本区别。
Ruby方法是通过表单“消息传递”调用的,不需要显式的第一类函数(有lift methods方法进入“正确的”函数对象) - 在这方面,Ruby类似于Smalltalk中。
Python的工作方式更像JavaScript(甚至是Perl),其中方法是直接调用的函数(还有存储的上下文信息,但是......)
虽然这看起来像是一个“次要”细节,但它实际上只是Ruby和Python设计的不同的表面。 (另一方面,它们也完全相同: - )
一个实际的区别是Ruby中method_missing
的概念(无论好坏,似乎在一些流行的框架中使用)。在Python中,可以(至少部分地)使用__getattr __ / __ getattribute__来模拟行为,尽管是非惯用的。
答案 31 :(得分:0)
有人给出的嵌套词汇范围示例有几个好处。
我认为这是两种语言之间差异的一个很好的例子。 Ruby更灵活。 Python可以是灵活的,但是你经常需要做极端的扭曲来实现目标,这使得它不值得麻烦。
很抱歉没有在原始答案下发帖,我想我没有权限这样做。
答案 32 :(得分:0)
有人建议Ruby的块可能被Python的上下文管理器“替换”。事实上,块允许比Python的上下文管理器更多。
块的接收方法可以在某个对象的上下文中执行块,从而允许块调用另外不可缓存的方法。 Python的生成器也不能这样做。
一个简单的例子可能会有所帮助:
class Proxy
attr_accesor :target
def method &block
# Ruby 1.9 or in Rails 2.3
target.instance_exec &block
end
end
class C
private
def hello
puts "hello"
end
end
p = Proxy.new
c = C.new
p.target = c
p.method { hello }
在此示例中,块{ hello }
中的方法调用在目标对象c
的上下文中具有真实意义。
此示例仅用于说明目的。在另一个对象的上下文中使用这种执行的实际代码并不罕见。例如,监控工具Godm使用它。
答案 33 :(得分:-2)
我很惊讶没有人提到过Singleton方法。
a=[]
b=[]
def b.some_method do ... end
b.some_method #fine
a.some_method #raises exception
它提供了对开放类概念的精细控制。您还可以使用Eigenclasses将模块混合到特定对象中,而不是给定类的所有对象。
o=Object.new
class << o
include SomeModule
end
如果不使用丑陋的黑客攻击,Python也没有switch语句,这会降低代码的可读性。
Ruby没有语句,只有表达式。这增加了很多灵活性。
你可以获得对任何方法的引用并传递它。
a=[]
m=a.method :map #m is now referencing an instance of Method and can be passed like any other reference to an object and is invoked with the call method and an optional block
易于嵌套的词法范围,提供受控的全局变量。
lambda {
global=nil
def Kernel.some_global= val
global||=val
end
def Kernel.some_global
global
end
}.call
一旦调用了lambda,global就超出了范围,但你可以设置它(在这个例子中只有一次),然后在你的程序中的任何地方访问它。希望这个价值很明确。
在Ruby中创建DSL比在Python中容易得多。在Python中创建类似Rake或RSpec的东西是可能的,但这将是一场噩梦。所以要回答你的问题,Ruby比Python有更多的灵活性。它不是Lisp的灵活性级别,但可以说是最灵活的OO语言。
Python非常棒,但与Ruby相比它非常僵硬。 Ruby不那么冗长,更具可读性(因为它读得更接近自然语言),python读起来像英语翻译成法语。
Python也很烦人,因为它的社区总是与Guido保持同步,如果Guido说你不需要功能X,社区中的每个人都相信它并鹦鹉学舌。它导致了一个陈旧的社区,有点像Java社区,根本无法理解匿名函数和闭包会给你带来什么。 Python社区并不像Haskell那样烦人,但仍然如此。
答案 34 :(得分:-3)
我是否提到Ruby有一个开发人员的EPIC社区。 Ninja主题灵感来自Object Oriented Ruby: Classes, Mixins and Jedi。
Ruby使用单一继承获得继承权!需要使用多重继承来表达域关系是系统设计不当的症状。多重继承产生的混淆不值得增加功能。
假设您有一个名为kick的方法:
def kick
puts "kick executed."
end
如果在 Ninjutsu 和 Shaolin 类中定义了 kick ,该怎么办?多重继承在这里失败,这就是Python失败的原因:
class Mortal < Ninjutsu, Shaolin
def initialize
puts "mortal pwnage."
end
end
在Ruby中,如果你需要忍者,你可以创建一个 Ninja 类的实例。如果你需要一个少林大师,你可以创建一个 Shaolin 类的实例。
ninja = Ninjutsu.new
ninja.kick
or
master = Shaolin.new
master.kick
忍者和少林大师都有可能分享相同的踢法技巧。再次阅读 - 两者都有相同的行为 - 没有别的! Python会鼓励你推出一个全新的课程。不是Ruby!在Ruby中,您只需使用Mixin:
module Katas
def kick
puts "Temporal Whip Kick."
end
end
简单地将Katas模块混合到Ruby类中:
require 'Katas'
class Moral < Ninjutsu
include Katas
def initialize
puts "mortal pwnage."
end
end
然后分享行为 - 这就是你真正想要的。不是整个班级。这是Ruby和Python之间的最大区别 - Ruby正确地继承了它!
答案 35 :(得分:-4)
虽然功能在很大程度上是相同的(特别是在Turing意义上),但恶意语言声称Ruby是为Pythonistas创建的,不能与Perlish编码风格分开。