当前位置:  开发笔记 > 编程语言 > 正文

Ruby没有Python,反之亦然?

如何解决《Ruby没有Python,反之亦然?》经验,为你挑选了23个好方法。

有很多关于Python与Ruby的讨论,我发现它们完全没有用,因为它们都转向了为什么功能X在语言Y中很糟糕,或者声称语言Y没有X,尽管事实上确实如此.我也确切地知道为什么我更喜欢Python,但这也是主观的,并且不会帮助任何人选择,因为他们可能没有和我一样的开发品味.

因此,客观地列出差异将是有趣的.所以没有"Python的lambdas糟透了".而是解释Ruby的lambdas可以做什么,Python不能.没有主观性.示例代码很好!

请不要在一个答案中有几个不同之处.并且对那些你认识的是正确的进行投票,然后对你所知道的那些是不正确的(或者是主观的).此外,语法上的差异也不大.我们知道Python使用缩进来处理Ruby用括号和结尾做什么,并且@在Python中称为self.

更新:这是一个社区维基,所以我们可以在这里添加很大的差异.

Ruby在类体中有一个类引用

在Ruby中,您可以在类主体中引用类(self).在Python中,在类构造完成之前,您没有对类的引用.

一个例子:

class Kaka
  puts self
end

在这种情况下,self就是类,这段代码会打印出"Kaka".无法打印出类名或以其他方式从Python中的类定义体(外部方法定义)访问该类.

所有类在Ruby中都是可变的

这使您可以开发核心类的扩展.以下是rails扩展的示例:

class String
  def starts_with?(other)
    head = self[0, other.length]
    head == other
  end
end

Python(想象没有''.startswith方法):

def starts_with(s, prefix):
    return s[:len(prefix)] == prefix

您可以在任何序列(不仅仅是字符串)上使用它.为了使用它,你应该明确地导入它,例如,from some_module import starts_with.

Ruby具有类似Perl的脚本功能

Ruby拥有一流的regexp,$ -variables,awk/perl逐行输入循环和其他功能,使其更适合编写munge文本文件的小shell脚本或充当其他程序的粘合代码.

Ruby有一流的延续

感谢callcc声明.在Python中,您可以通过各种技术创建延续,但是该语言没有内置支持.

Ruby有块

使用"do"语句,您可以在Ruby中创建一个多行匿名函数,它将作为参数传递到do前面的方法中,并从那里调用.在Python中,您可以通过传递方法或使用生成器来执行此操作.

红宝石:

amethod { |here|
    many=lines+of+code
    goes(here)
}

Python(Ruby块对应于Python中的不同构造):

with amethod() as here: # `amethod() is a context manager
    many=lines+of+code
    goes(here)

要么

for here in amethod(): # `amethod()` is an iterable
    many=lines+of+code
    goes(here)

要么

def function(here):
    many=lines+of+code
    goes(here)

amethod(function)     # `function` is a callback

有趣的是,Ruby中用于调用块的便捷语句称为"yield",在Python中将创建一个生成器.

红宝石:

def themethod
    yield 5
end

themethod do |foo|
    puts foo
end

蟒蛇:

def themethod():
    yield 5

for foo in themethod():
    print foo

虽然原则不同,但结果却非常相似.

Ruby更容易支持功能样式(管道式)编程

myList.map(&:description).reject(&:empty?).join("\n")

蟒蛇:

descriptions = (f.description() for f in mylist)
"\n".join(filter(len, descriptions))

Python有内置生成器(像Ruby块一样使用,如上所述)

Python支持该语言的生成器.在Ruby 1.8中,您可以使用生成器模块,该模块使用continuation从块创建生成器.或者,您可以使用块/ proc/lambda!而且,在Ruby 1.9中,Fibers是,并且可以用作生成器,而Enumerator类是一个内置的生成器4

docs.python.org有这个生成器示例:

def reverse(data):
    for index in range(len(data)-1, -1, -1):
        yield data[index]

将其与上述块示例进行对比.

Python具有灵活的名称空间处理

在Ruby中,当您导入文件时require,该文件中定义的所有内容都将在您的全局命名空间中结束.这导致命名空间污染.解决方案是Rubys模块.但是,如果使用模块创建命名空间,则必须使用该命名空间来访问包含的类.

在Python中,文件是一个模块,您可以导入其包含的名称from themodule import *,从而在需要时污染命名空间.但您也可以使用from themodule import aname, another或只是导入选定的名称,import themodule然后使用themodule.aname.如果您希望在命名空间中有更多级别,则可以使用包,这些包是包含模块和__init__.py文件的目录.

Python有文档字符串

Docstrings是附加到模块,函数和方法的字符串,可以在运行时进行内省.这有助于创建帮助命令和自动文档等内容.

def frobnicate(bar):
    """frobnicate takes a bar and frobnicates it

       >>> bar = Bar()
       >>> bar.is_frobnicated()
       False
       >>> frobnicate(bar)
       >>> bar.is_frobnicated()
       True
    """

Ruby的等价物类似于javadocs,位于方法之上而不是在其中.可以使用1.9的Method#source_location 示例使用在运行时从文件中检索它们

Python有多重继承

Ruby没有("故意" - 请参阅Ruby的网站,请参阅此处如何在Ruby中完成).它确实将模块概念重用为一种抽象类.

Python有list/dict理解

蟒蛇:

res = [x*x for x in range(1, 10)]

红宝石:

res = (0..9).map { |x| x * x }

蟒蛇:

>>> (x*x for x in range(10))
 at 0xb7c1ccd4>
>>> list(_)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

红宝石:

p = proc { |x| x * x }
(0..9).map(&p)

Python 2.7+:

>>> {x:str(y*y) for x,y in {1:2, 3:4}.items()}
{1: '4', 3: '16'}

红宝石:

>> Hash[{1=>2, 3=>4}.map{|x,y| [x,(y*y).to_s]}]
=> {1=>"4", 3=>"16"}

Python有装饰器

类似于装饰器的东西也可以用Ruby创建,也可以说它们不像Python那样必要.

语法差异

Ruby需要"end"或"}"来关闭它的所有作用域,而Python只使用white-space.最近Ruby已经尝试允许只有空格的缩进http://github.com/michaeledgar/seamless



1> John Feminel..:

Ruby具有的概念,这些基本上是围绕一段代码的语法糖; 它们是一种创建闭包并将它们传递给另一种可能使用或不使用该块的方法的方法.稍后可以通过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,但它没有完全有块,因为它缺少一些有用的语法糖.但是,至少有一种方法可以以临时方式获得它.例如,请参见此处.


我是一名Python程序员.我想看一个例子,说明Ruby块如何帮助你编写比Python更简洁或更美观的东西,因为它没有块.您的示例可以写成:对于[1,2,3,4]中的i:print(i + 5).它不使用块,但它的简洁和美观以及ruby每个例子.
@Manuel,procs可用于将函子附加到非平凡的数据结构(树,图......),这些数据结构不能"循环",因此需要横向的特殊迭代器.块是匿名触发器,允许您在一个表达式(与定义然后实现)中实现仿函数,这大大加快了编码过程并澄清了意图.例如,如果你正在创建一个图形数据结构,你可以定义一个'each'迭代器然后mixin Enumerable,它会立即让你访问几十个迭代器(sort,all?,any?,grep).现在你打电话给一个街区......
@Lennart:除了你的例子之外,它也很糟糕,它在语法上也是错误的.
@RommeDeSerieux,因为它需要语言中的名字!而且,它是一个功能对象,而不是一个功能.让我们看一下Ruby Docs:"Proc对象是已绑定到一组局部变量的代码块",因此匿名Proc只是*block*而且它当然不仅仅是一个函数!
@unbeknow:A,对.但如果那是一个功能而不是印刷品,它就会起作用.在python 3中这有效:[print(e + 5)for e in [1,2,3,4]]当谈到可怕时,我认为上面的红宝石代码很可怕,所以这显然是主观的,因而不是这个问题的一部分.@John我不是说它是等价的,我说这与你的例子有什么区别并不明显.@Bastien,不,但你可以做类似的事情并不意味着他们是一样的.即使有其他方法,也应列出这里的差异.
好吧,我不能评论ruby代码,我只是一个Python程序员.但我要指出的是,即使某些事情在语法上允许你最好不要这样做(比如使用像副作用的列表理解这样的功能构造).原因可能是对其不满的社区或禁止它的一般软件开发原则.因此OP对A和B所具有的功能的问题可能在实践中有点误导,因为没有人在A中使用此功能.
@RommeDeSerieux:他们是匿名函数,是的,但与Ruby块和Python lambdas的区别在于块不是一等公民.与"一切都是一个对象"的哲学相反,这些哲学似乎在其他方面普遍存在,块不是对象,你必须将它们打包并取消装箱.有关一些有趣的详细信息,请参阅http://innig.net/software/ruby/closures-in-ruby.rb和http://stackoverflow.com/questions/2946603/ruby-convert-proc-to-lambda

2> Glenn Maynar..:

Python示例

函数是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的函数不是一流的对象

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!"    


通过该标记,常见的lisp函数不是'firstclass'也不是scala的...
你很困惑.第一类对象由赋值赋值:`x = y`,而不是通过调用`self.class.send(:define_method,:func,method(:func2))`.您的"反例"显示了Ruby的功能如何不是一流的.如果您不同意,请随意发布您自己的答案; 不要在我的混乱中坚持下去.
在ruby中由`def ... end`定义的东西不是函数.它们是方法(你定义它们的方式,`Kernel`).方法可以是未绑定的(使用`#method`方法),然后是对象.ruby最接近函数的是`Proc`实例,它们也是对象,可以传递或调用.它还有一个特殊的语法,用于将单个回调`Proc`传递给方法,正如John Feminella讨论[在他的回答中](http://stackoverflow.com/questions/1113611/what-does-ruby-have-that-蟒-犯规和 - 反之亦然/ 1113624#1113624).
@Glenn:美丽是旁观者的眼睛.尽管如此,通过实现定义,方法是一流的对象(在这种情况下,我指的是维基百科的定义).也许,你还有其他一流的定义?他们是否需要一张Platinum Frequent Flier Card来升级到头等舱?
@Glenn:我得到你所说的,但我对Ruby重新定义函数 - 方法是一个单独的语义概念的断言狡辩.如果你想玩定义游戏,大多数命令式代码是程序,而不是函数.我并不是想要变得困难,只是因为我认为定义和准确性很重要.我同意操纵'UnboundMethod`可以是PITA,tho.
@Glenn查看SO FAQ部分"其他人可以编辑我的东西?!" - 这是一个社区维基.
你反复编辑我的答案,偏向于你的宠物语言,而且为了不断地浪费我的时间在我几个月前提供的答案而且不想反复回归,你通常表现得不成熟.我怀疑SO管理员会感激你浪费他们的时间,因为我感谢你浪费我的时间.长大.
@bias:方法是第一类对象,但它们只是块的包装,它们不是第一类对象.Block是代表Ruby中函数的基础,基本概念.因为它不是一个对象,所以你总是必须将它打包并将其打包,方法是将它包装在Proc(lambda或不是lambda)或Method中.然后,当您想要将Proc或方法传递给需要块的代码(使用&显式声明或者与yield一起隐式使用)时,您必须使用&运算符将其取消装箱.
@rampion:函数是具有单个入口点的代码块,可以获取参数和返回值.方法是一种功能.Ruby不会重新定义函数,以便假装它比其他人更特别,或者作为处理它们的糟糕程度的借口.那只是挥手.
只要这个答案在前面有我的名字,你就不会*编辑它来说出与我所说的完全不同的东西.这是一种不幸的错误归因.如果您愿意,请提交您自己的答案.从你的评论中你显然是在拖钓,所以我不会和你讨论任何问题.
@Glenn我编辑了帖子,以便人们知道你发布的内容和我发布的内容.我还添加了分歧的概要.这是一个客观的语言问题,我们不要将这种主观性转变为火焰/回滚战争.
您正在编辑此项以替换您不喜欢的位置; 这是*不合适的*编辑.再次,并且最后一次,如果您希望这样做,请添加您自己的答案.我不会一直重复自己; 再次重复这个幼稚的编辑,它将被还原而不予评论."添加另一个答案"按钮就在底部.

3> Mark Thomas..:

最终所有的答案在某种程度上都是主观的,到目前为止发布的答案几乎证明了你不能指出任何一种在另一种语言中不可行的功能同样不错(如果不是相似)的方式因为这两种语言都非常简洁和富有表现力.

我喜欢Python的语法.但是,你必须比语法更深入地挖掘Ruby的真正美.Ruby的一致性具有禅宗般的美感.虽然没有一个简单的例子可以完全解释这一点,但我会试着在这里提出一个来解释我的意思.

反转此字符串中的单词:

sentence = "backwards is sentence This"

当您考虑如何做到这一点时,您将执行以下操作:

    将句子分成单词

    颠倒话语

    将单词重新连接回字符串

在Ruby中,你会这样做:

sentence.split.reverse.join ' '

正如你所想的那样,在同一个序列中,一个方法一个接一个地调用.

在python中,它看起来更像是这样的:

" ".join(reversed(sentence.split()))

这并不难理解,但它并没有完全相同的流程.主语(句子)埋在中间.这些操作是函数和对象方法的混合.这是一个简单的例子,但是当真正使用和理解Ruby时,会发现许多不同的例子,特别是在非平凡的任务上.



4> Jason Baker..:

Python有一个"我们都是成年人在这里"的心态.因此,你会发现Ruby有像常量这样的东西,而Python却没有(尽管Ruby的常量只会引发警告).Python的思维方式是,如果你想使某些东西保持不变,你应该将变量名称放在所有大写字母中而不是改变它.

例如,Ruby:

>> PI = 3.14
=> 3.14
>> PI += 1
(irb):2: warning: already initialized constant PI
=> 4.14

蟒蛇:

>>> PI = 3.14
>>> PI += 1
>>> PI
4.1400000000000006


哈......这只是提醒我,至少在python 2.*中,你能够做到"真,假=假,真"......我相信他们已经在python 3.0中正确修复了......那就是你*应该*被阻止做.
@Jason"我们这里都是大人"是对事实的陈述?我想把这个意见称为围绕一个特征,因此投票结果.
就个人而言,我喜欢该语言强制执行的严格指导原则,因为它使用该语言编写的所有代码都保持一致.它*迫使你遵循指导原则,阅读代码的开发人员可以一目了然地了解它是什么.虽然大多数Python编码器都使用相同的通用"样式",但我看到了一些在Ruby中无法实现的非常大的不一致性.
@bias - 我不确定你为什么要贬低我.这个答案不同意或不同意python的做事方式.这只是一个事实陈述.
@bias - 说"我们都是成年人"并不是轻微的意思.这是一个非正式的Python座右铭,我相信这里最好解释一下:http://mail.python.org/pipermail/tutor/2003-October/025932.html
-1似乎成年人做出了明智的决定,而且只有孩子才会做出改变而不用担心后果**.Ruby告诉你,你正在做一些奇怪的事情,因为你是一个知情的成年人,它可以让你做出改变.
你喜欢这种(python)自己的思维方式吗?只是好奇.
@Tom:是的,真假只是内置bool实例.:)在python 3中,他们也将它们添加到关键字中,因此您无法使用这些名称创建新变量.@musicfreak:我不介意STYLE强制执行.毕竟,这就是Python缩进的原因.;-)这就是私有方法和我不喜欢的东西.例如,我通常可以停止合理的代码重用.
@Lennart什么?你可以在ruby中使用私有方法 - 只需使用反射!*私人*只是隐藏了意外使用的方法(比如导弹发射器上的触发器上的盖板 - 有时候它**确保人们*实际上*想要做某事).实际上,所有反Ruby论点似乎都源于缺乏对Ruby的理解.

5> Geo..:

您只能从Python中导入模块中的特定函数.在Ruby中,您可以导入整个方法列表.你可以在Ruby中"取消"它们,但它并不是它的全部内容.

编辑:

让我们来看看这个Ruby模块:

module Whatever
  def method1
  end

  def method2
  end
end

如果你把它包含在你的代码中:

include Whatever

你会看到method1method2都已添加到你的命名空间中.您不能仅导入method1.您可以同时导入它们,也可以根本不导入它们.在Python中,您只能导入您选择的方法.如果这个名称可能会被称为选择性导入?


Ruby实际上没有与python具有相同意义的模块系统.要求基本上作为文本包含工作,一些检查是否存在重复包含.您可以(ab)使用模块作为命名空间但是`module`实际上有点用词不当.模块基本上是没有`new`,`allocate`方法的类.它们最适合作为基于每个类/对象共享代码的方式,而不是分区库或跨程序共享代码的机制.
这不会导致很多名称空间混乱吗?
啊对!Python喜欢命名空间.Ruby的情况不是这样吗?你不要'导入bla; 在Ruby中的bla.foo()`
您只能导入函数a,而不能导入所有函数.例如,如果您包含一个声明3个非静态函数的Ruby模块,那么您可以将它们全部包含在命名空间中.在python中你必须从模块导入*写.

6> 小智..:

来自Ruby的网站:

相似之处与Python一样,在Ruby中......

有一个交互式提示(称为irb).

您可以在命令行上读取文档(使用ri命令而不是pydoc).

没有特殊的行终止符(通常的换行符除外).

字符串文字可以跨越多行,如Python的三引号字符串.

括号用于列表,括号用于dicts(在Ruby中,称为"哈希").

数组的工作方式相同(添加它们会产生一个长数组,但是像这样组成它们a3 = [ a1, a2 ]会给你一个数组数组).

对象强烈且动态地键入.

一切都是对象,变量只是对象的引用.

虽然关键字有点不同,但异常的工作方式大致相同.

你有嵌入式doc工具(Ruby的名字叫做rdoc).

差异与Python不同,在Ruby中......

字符串是可变的.

您可以创建常量(您不打算更改其值的变量).

有一些强制执行的案例约定(例如,类名以大写字母开头,变量以小写字母开头).

只有一种列表容器(一个数组),它是可变的.

双引号字符串允许转义序列(如\ t)和特殊的"表达式替换"语法(允许您将Ruby表达式的结果直接插入到其他字符串中,而无需"添加"+"字符串"+"在一起") .单引号字符串就像Python的r"原始字符串".

没有"新风格"和"旧风格"课程.只是一种.

您永远不会直接访问属性.使用Ruby,它是所有方法调用.

方法调用的括号通常是可选的.

有公共,私有和受保护来强制访问,而不是Python _voluntary_ underscore __convention__.

使用"mixin"而不是多重继承.

您可以添加或修改内置类的方法.这两种语言都可以让你随时打开和修改类,但是Python阻止了对内置函数的修改 - 而Ruby则没有.

你有真和假而不是真和假(和零而不是无).

当测试真相时,只有false和nil评估为假值.其他一切都是真的(包括0,0.0,""和[]).

这是elsif而不是elif.

它需要而不是导入.否则,用法是一样的.

关于事物上面的行(而不是它们下面的文档字符串)的通常风格的注释用于生成文档.

有许多快捷方式,虽然可以让你记住更多,但你很快就会学到.他们倾向于使Ruby变得有趣并且非常高效.


"这需要而不是导入.否则,用法是相同的." 似乎完全不准确.

7> haffax..:

Ruby拥有的是它的脚本语言功能.在此上下文中的脚本语言意味着在shell脚本和一般文本操作中用于"粘合代码".

这些主要与Perl共享.一流的内置正则表达式,$ -Variables,有用的命令行选项,如Perl(-a,-e)等.

结合其简洁而又灵巧的语法,它非常适合这类任务.

Python对我来说更像是一种动态类型的商业语言,它非常容易学习并且语法清晰.不像Ruby那样酷"但很整洁".Python对我来说是对其他lib的大量绑定.绑定到Qt和其他GUI库,许多游戏支持库和和.Ruby少得多.虽然很多用于数据库的绑定具有良好的质量,但我发现在Python中更好地支持利基库,即使对于相同的库也存在Ruby绑定.

所以,我会说两种语言都有它的用途,它的任务是定义使用哪种语言.两者都很容易学习.我并排使用它们.用于脚本的Ruby和用于独立应用程序的Python.


不完全是,实际上我的意思是预定义的变量,如$ _,$ 1等.这些变量由ruby本身自动填充.$ _是读取的最后一行.$ 1,$ 2等是最后一场比赛的正则表达式匹配.请参阅此处获取完整列表:http://www.zenspider.com/Languages/Ruby/QuickRef.html#17它基本上是针对紧凑脚本的黑客攻击.您也可以通过API调用获取所有信息,但使用$ variables它更简洁.这种变量不适合Python的风格,他们故意将它们排除在外.

8> Chuck..:

我不认为"Ruby有X而Python没有,而Python有Y而Ruby没有"是最有用的方式来看待它.它们是非常相似的语言,具有许多共享能力.

在很大程度上,差异在于语言的优雅和可读性.使用你提出的一个例子,理论上它们都有lambdas,但Python程序员倾向于避免它们,并且使用它们构造的构造看起来不像Ruby那样可读或惯用.所以在Python中,一个优秀的程序员会想要采用不同的方法来解决问题而不是Ruby,因为它实际上更好的方法.


我同意lambdas的范围有限,在许多情况下都没用.但是,我不认为说Python程序员像瘟疫一样避免使用它们是公平的.
你可以"混合使用Enumerable"与发生器,并立即获得30个新的和精彩的迭代器吗?在理解为什么块/过程很好之前,你需要先查看整体语言.
@Lennart:Multiline块一直在Ruby中使用 - 实际上比我在用于惯用Python代码时使用的lambdas更常见.有关常见示例,请参阅http://info.michael-simons.eu/2007/08/06/rails-respond_to-method/.

9> Christos Hay..:

我想建议一个原始问题的变体,"Ruby有什么不具备Python,反之亦然?" 它承认了令人失望的答案,"那么,你能用Ruby或者Python做什么,而Intercal无法做到这一点?" 在这个层面上没有任何东西,因为Python和Ruby都是坐在图灵近似宝座上的庞大王室的一部分.

但是这个怎么样:

什么可以在Python中优雅地完成,而不能在具有如此美丽和良好工程的Ruby中完成,反之亦然?

这可能比仅仅进行功能比较更有趣.



10> Dario..:

Python有一个用于list-comprehenions和generator的显式内置语法,而在Ruby中你可以使用map和code blocks.

相比

list = [ x*x for x in range(1, 10) ]

res = (1..10).map{ |x| x*x }



11> 小智..:

"以大写字母开头的变量变为常量,无法修改"

错误.他们能.

如果你这样做,你只会收到警告.


如果某种语言为您提供操作警告,我认为您可以将操作视为"不可能".其他任何事都是疯狂的.

12> Jack Lloyd..:

在基础设施方面更多:

Python与C++(通过诸如Boost.Python,SIP和Py ++之类的东西)比Ruby 更好地集成,其中的选项似乎是直接针对Ruby解释器API(当然,你也可以用Python做).但是在这两种情况下这样做都是低级别,单调乏味且容易出错)或者使用SWIG(虽然它可以工作,如果你想支持多种语言肯定很棒,但是它不如Boost.Python或SIP那么好你特意想要绑定C++).

Python有许多Web应用程序环境(Django,Pylons/Turbogears,web.py,可能至少有六个其他),而Ruby(有效)有一个:Rails.(其他Ruby Web框架确实存在,但似乎很难对Rails产生很大的影响).这个方面好还是坏?很难说,也许很主观; 我可以很容易地想象Python情况更好并且Ruby情况更好的论点.

在文化方面,Python和Ruby社区似乎有所不同,但我只能暗示这一点,因为我没有那么多与Ruby社区交互的经验.我主要是希望那些对两者都有很多经验的人可以放大(或拒绝)这种说法.


你的第二点充其量是错误的.你应该先看看Rack和Sinatra
我明确指出存在其他Rails堆栈; 我只是觉得没有人真正使用它们.检查Sinatra和Rack并没有完全改变这种印象.您是否真的认为,例如,Sinatra(总共有34个问题),或者露营(总共2个SO问题),或者其他任何一个,实际上是否有真正的用户群/社区?据我所知,他们中的大多数甚至没有现实生活中的用户.比较Django(4K +)或Rails(7K +),甚至web.py.

13> OscarRyz..:

无耻地复制/粘贴来自:亚历克斯·马尔泰利的答案对" 什么是关于Ruby比Python更好 "从线程comp.lang.python的邮件列表.

2003年8月18日上午10点50分,Erik Max Francis写道:

"Brandon J. Van Every"写道:

Ruby比Python有什么好处?我确定有一些东西.它是什么?

问问Ruby人员而不是Python人员会不会更有意义?

可能会,也可能不会,取决于一个人的目的 - 例如,如果一个人的目的包括Python社区的"社会学研究",那么向该社区提出问题可能会更多地揭示有关它的信息,而不是将它们放在其他地方:-).

Personally, I gladly took the opportunity to follow Dave Thomas' one-day Ruby tutorial at last OSCON. Below a thin veneer of syntax differences, I find Ruby and Python amazingly similar -- if I was computing the minimum spanning tree among just about any set of languages, I'm pretty sure Python and Ruby would be the first two leaves to coalesce into an intermediate node:-).

Sure, I do get weary, in Ruby, of typing the silly "end" at the end of each block (rather than just unindenting) -- but then I do get to avoid typing the equally-silly ':' which Python requires at the start of each block, so that's almost a wash:-). Other syntax differences such as '@foo' versus 'self.foo', or the higher significance of case in Ruby vs Python, are really just about as irrelevant to me.

Others no doubt base their choice of programming languages on just such issues, and they generate the hottest debates -- but to me that's just an example of one of Parkinson's Laws in action (the amount on debate on an issue is inversely proportional to the issue's actual importance).

Edit (by AM 6/19/2010 11:45): this is also known as "painting the bikeshed" (or, for short, "bikeshedding") -- the reference is, again, to Northcote Parkinson, who gave "debates on what color to paint the bikeshed" as a typical example of "hot debates on trivial topics". (end-of-Edit).

我发现一个重要的语法差异,并且有利于Python - 但其他人无疑会认为恰恰相反 - 是"你怎么称呼一个不带参数的函数".在Python中(比如在C中),要调用一个函数,你总是应用"调用操作符" - 在你调用的对象之后的尾随括号(在那些尾随括号内)去你在调用中传递的args - 如果你没有传递args,那么括号是空的).这仅仅提到了 任何一个 object, with no operator involved, as meaning just a reference to the object -- in any context, without special cases, exceptions, ad-hoc rules, and the like. In Ruby (like in Pascal), to call a function WITH arguments you pass the args (normally in parentheses, though that is not invariably the case) -- BUT if the function takes no args then simply mentioning the function implicitly calls it. This may meet the expectations of many people (at least, no doubt, those whose only previous experience of programming was with Pascal, or other languages with similar "implicit calling", such as Visual Basic) -- but to me, it means the mere mention of an object may EITHER mean a reference to the object, OR a call to the object, depending on the object's type -- and in those cases where I can't get a reference to the object by merely mentioning it I will need to use explicit "give me a reference to this, DON'T call it!" operators that aren't needed otherwise. I feel this impacts the "first-classness" of functions (or methods, or other callable objects) and the possibility of interchanging objects smoothly. Therefore, to me, this specific syntax difference is a serious black mark against Ruby -- but I do understand why others would thing otherwise, even though I could hardly disagree more vehemently with them:-).

在语法下面,我们在基本语义学中遇到了一些重要的差异 - 例如,Ruby中的字符串是可变对象(比如在C++中),而在Python中它们是不可变的(比如在Java中,或者我相信C#).同样,主要通过他们已经熟悉的东西来判断的人可能认为这对Ruby来说是一个加分(除非他们熟悉Java或C#,当然:-).我,我认为不可变的字符串是一个很好的想法(我并不奇怪Java,我认为,它重新发明了已经在Python中的那个想法),尽管我不介意拥有"可变字符串缓冲区"类型(理想情况下,它比Java自己的"字符串缓冲区"更易于使用); 在学习Java之前,我不会因为熟悉而给出这个判断, all data are immutable, all the languages I knew had mutable strings -- yet when I first saw the immutable-string idea in Java (which I learned well before I learned Python), it immediately struck me as excellent, a very good fit for the reference-semantics of a higher level programming language (as opposed to the value-semantics that fit best with languages closer to the machine and farther from applications, such as C) with strings as a first-class, built-in (and pretty crucial) data type.

Ruby在基本语义方面确实有一些优势 - 例如,删除Python的"列表与元组"非常微妙的区别.但主要是得分(因为我保持它,简单是一个大的加分和微妙的,聪明的区别,一个显着的减去)是对Ruby(例如,有闭合和半开放的间隔,符号a..b和.. .b [任何人都想声称这显然是哪个? - )],当然是傻 - 恕我直言!).再一次,那些认为在语言的核心有很多相似但略有不同的东西的人,而不是MINUS,当然会将这些"另一种方式"从我如何计算中算起来:-).

不要被这些比较误导,认为这两种语言 非常相似不同,请注意.他们不是.但是,如果我被要求将"capelli d'angelo"与"spaghettini"进行比较,在指出这两种意大利面几乎与任何人无法区分并且可以在任何你想要准备的菜中互换时,我将不可避免地要进入显微镜检查长度和直径如何不知不觉地变化,如何在一个案例中而不是在另一个案例中使股线的末端逐渐变细,等等 - 试图解释为什么我个人宁愿有capelli d 'angelo作为任何种类的肉汤中的意大利面,但更喜欢spaghettini作为pastasciutta与适当的调味汁配合如此长的薄面食形式(橄榄油,蒜末,切碎的红辣椒和精细的凤尾鱼,例如 - 但如果你切大蒜和辣椒而不是切碎它们,那么你应该选择意大利面条的发声器体而不是spaghettini的更薄的消逝,并且建议放弃achovies并添加一些新鲜的春天罗勒[甚至 - 我是异教徒......! - 薄荷......叶子 - 在送餐前的最后一刻).哎呀,抱歉,这表明我正在国外旅行,并且暂时没有意大利面,我想.但这个比喻还是不错的! - ) - 薄荷......叶子 - 在送餐前的最后一刻).哎呀,抱歉,这表明我正在国外旅行,并且暂时没有意大利面,我想.但这个比喻还是不错的! - ) - 薄荷......叶子 - 在送餐前的最后一刻).哎呀,抱歉,这表明我正在国外旅行,并且暂时没有意大利面,我想.但这个比喻还是不错的! - )

所以,回到Python和Ruby,我们来看两个大问题(就语言本身而言 - 离开库,以及其他重要的辅助工具,如工具和环境,如何嵌入/扩展每种语言等等),它现在 - 它们不会适用于每种语言的所有实现,例如,Jython vs Classic Python是Python语言的两个实现!):

    Ruby的迭代器和代码块与Python的迭代器和生成器相比;

    Ruby的TOTAL,肆无忌惮的"动态性",包括
    "重新打开"任何现有类的能力,包括所有内置类,并在运行时改变其行为 - 与Python的巨大但 有限的 动态性相比,它永远不会改变现有的行为内置类及其实例.

就个人而言,我认为1一洗(差异是如此之深,我可以很容易地看到人们憎恨任何一种方法和尊崇等,但就我个人的尺度优缺点只是甚至达到); 和2的一个关键问题-一个使Ruby更适合"修修补补",但是Python同样更适合在大型生产应用.在某种程度上,这很有趣,因为两种语言都比其他语言更具动态性,最终它们与我的POV之间的关键区别应该取决于那个 - 在这方面Ruby"十一"(参考文献)这里是"Spinal Tap",当然).在Ruby中,我能做到!即,我可以动态地改变内置字符串类,以便a ="Hello World"b ="hello world"如果a == b打印"相等!\n"否则打印"不同!\n"结束将打印"等于".在python中,我无法做到这一点.出于元编程,实现实验框架等目的,Ruby的这种惊人的动态能力非常强大 吸引力.但是 - 如果我们谈论的是大型应用程序,由许多人开发并且由更多人维护,包括来自不同来源的各种库,并且需要在客户端站点投入生产......好吧,我不想要一种非常动态的QUITE语言,非常感谢你.我厌恶一些图书馆的想法,无意中打破了依赖于那些不同字符串的其他不相关的图书馆 - 这就是那种深层隐藏的"渠道",在LOOK分开并且应该分开的代码之间,大规模的编程.通过让任何模块影响任何其他"隐蔽"的行为,改变内置类型的语义的能力只是生产应用程序编程的一个不好的想法,

如果我不得不将Ruby用于这么大的应用程序,我会尝试依赖编码风格的限制,大量的测试(无论什么时候改变都要重新运行 - 甚至应该完全无关......),等等,禁止使用此语言功能.但是在我看来,没有首先使用该功能甚至更好 - 正如Python本身对于应用程序编程来说是更好的语言,如果一定数量的内置命令可能被"钉死",那么我就知道了例如,len("ciao")是4(而不必担心是否有人在内置模块中更改了名称'len'的绑定...).我希望最终Python能够"确定"其内置插件.

但这个问题很小,因为重新绑定内置函数在Python中已经被弃用了,也是一种罕见的做法.在Ruby中,它让我觉得很重要 - 就像 其他语言的功能太强大(例如,Dylan)在我看来存在类似风险一样(我希望Python永远不会得到如此强大的宏系统,不重要的是"让人们定义他们自己的语言本身嵌入的特定领域的小语言" - 恕我直言,它会削弱Python对应用程序编程的极大用处,通过向可能的修补匠提出"有吸引力的麻烦"潜伏在每个程序员心中...).

亚历克斯



14> Anon..:

其他一些来自:

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



15> Lennart Rege..:

我不确定这一点,所以我先把它作为答案添加.

Python将未绑定的方法视为函数

这意味着你可以调用一个方法要么喜欢theobject.themethod()或通过TheClass.themethod(anobject).

编辑:虽然方法和函数之间的差异在Python中很小,而在Python 3中不存在,但它在Ruby中也不存在,仅仅因为Ruby没有函数.定义函数时,实际上是在Object上定义方法.

但你仍然不能采用一个类的方法并将其作为一个函数调用,你必须将它重新绑定到你想要调用的对象,这是更加顽固的.



16> 小智..:

我想提一下Python描述符API,它允许一个自定义对象到属性的"通信".值得注意的是,在Python中,可以通过覆盖通过方法的默认实现给出的默认值来自由地实现替代协议__getattribute__.让我提供有关上述内容的更多细节.描述是在普通类__get__,__set__和/或__delete__方法.当解释器遇到类似的东西时anObj.anAttr,执行以下操作:

__getattribute__方法anObj被调用

__getattribute__ 从类dict中检索anAttr对象

它检查abAttr对象是否具有__get__,__set____delete__可调用对象

上下文(即调用者对象或类,以及值,而不是后者,如果我们有setter)被传递给可调用对象

结果返回.

如前所述,这是默认行为.可以通过重新实现来自由地更改协议__getattribute__.

这种技术比装饰器更强大.



17> Dario..:

Ruby使用内置的持续支持callcc.

因此,您可以实现像amb-operator这样的酷事



18> John La Rooy..:

在这个阶段,Python仍然有更好的unicode支持



19> Lennart Rege..:

您可以在Ruby和Python中的类定义中包含代码.但是,在Ruby中,您可以引用类(self).在Python中,您没有对类的引用,因为该类尚未定义.

一个例子:

class Kaka
  puts self
end

在这种情况下,self就是类,这段代码会打印出"Kaka".无法打印出类名或以其他方式从Python中的类定义主体访问该类.


用例是什么?

20> rasjani..:

Python有文档字符串,ruby没有......或者如果没有,它们就像在python中一样容易访问.

PS.如果我错了,请多好,留下一个例子?我有一个解决方法,我可以非常容易地monkeypatch到类,但我想在"本地方式"有文档字符串类型的功能.


没有文档字符串,但是,确实有RDoc.所以是的,不是那么容易获得,而是100%隐藏.
是的,它被称为"Ruby Doctest".就doctests而言,真正重要的是你在某处包含可测试的代码片段的可读文档 - 无论是在docstring还是在注释中都没有区别.

21> fortran..:

Ruby有sigils和twigils,而Python则没有.

编辑:我忘记了一件非常重要的事情(毕竟,之前只是为了点火:-p):

Python有一个JIT编译器(Psyco),一种用于编写更快代码(Pyrex)的低级语言,以及添加内联C++代码(Weave)的能力.


好吧,如果你想走这条路:两者都是图灵完成的.其他一切都只是语法.

22> Pinochle..:

Ruby在命令行中对输入文件('-n'标志)进行逐行循环,因此可以像AWK一样使用.这个Ruby单线程:

ruby -ne 'END {puts $.}'

将计算像AWK单线的线:

awk 'END{print NR}'

Ruby通过Perl获取功能,Perl将其从AWK中获取,作为一种使用Perl获取系统管理员的方法,而无需改变他们的工作方式.



23> Scott Dugas..:

我的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
=> #

参考:http://blog.nuclearsquid.com/writingings/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指南


Python在括号中有*隐式行继续*(`,`[`或`{`
推荐阅读
TXCWB_523
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有