2006-09-25
Ruby和Python的语法差别
关键字: ruby python 比较 语法
布娃娃在另一个帖子提到很多差别,我觉得和那个主题不符,所以另外开一个贴讨论吧。
其实python和ruby非常接近,比大多数别的语言要接近的多,所以喜欢用啥就用啥(大实话,虽然也是废话)。语法上的差别虽然有那么一点,大部分是syntax sugar,我斗胆稍微列几个(python我也忘得差不多了,不对的大家尽管来鞭尸吧),但是主要差异还是设计思想上的:灵活vs明确. 我不认为两者在生产力上会有什么差别,如果你熟悉的话。*注意,仅限语言本身的比较。
1. ruby的case可以匹配很多东西:范围/数组,对象,正则表达,python没有case/switch而使用if/else比较死板点
2. python的缩进很漂亮,虽然有时会造成些许麻烦。ruby的end蛮难看的,所以大家都被逼当one liner(玩笑)
3. 感觉上ruby比python更OO,当然这也可能是因为python不提倡用那些改变对象内部构造的‘伎俩’造成的错觉
4. python有list comprehension, ruby没有:(
5. python有真正的keyword argument, ruby用hash模拟,当然实际用起来没什么差别
6. python的self很讨厌,ruby没有那种繁琐的东西
7. reflection,ruby内置了很多方法,比如object.methods,而python把这些信息存在特殊的字典里。差不多
8. ruby的block功能很强,python的lambda只能返回单一值
9. ruby的open class已经声明远播,可以玩出2.days.ago这样的花样,python好像没法直接修改内置类也反对这么做。
10. python需要用@classmethod修饰声明类方法,ruby是内建
11. ruby有单子方法,也就对对象单独定制,python不知道有没有类似概念
12. ruby有method_missing机制,python可以使用__getattr__截获未定义方法(from qiezi)
13. ruby使用单继承+mixin,python使用多重继承,不过python也有mixin
14. ruby有attr_*系列语法helper,省却自己写一堆setter/getter, python的property方法还是得自己写setter/getter
15. ruby和python都使用duck typing,不过python也有一套显式的interface机制(从zope3并入内核了么?)
16. ruby的函数调用括号是可省的,稍微少敲几下键盘。python默认没括号也不带参数的话返回函数本身的一个引用。
17. 我不清楚python的meta programming能到什么程度,只好等大牛来说说了。只是觉得pythoner不常用那个,也许觉得会把程序逻辑搞得晦涩不明。
18. ruby从perl继承了一部分难看的东西,比如很多预定义的$x常量
19. ruby内建正则表达,方便一点
20. ruby的yield是用来call block的。而python的yield是用来给generator输入输出值的。
21. python的库给我感觉命名规范有点不统一,有些方法用snake_case有些则用CamelCase,也许是库太多了遗留下的历史问题
22. python的三引号很漂亮,ruby的<<-XX...XX太难看了,也可以用%q{...}包裹多行文字(from qiezi)
23. ruby的类库设计中喜欢给方法添加别名,方便记忆。
另: ruby官方网站也提供了一些基本的比较。(from Robbin)
其实python和ruby非常接近,比大多数别的语言要接近的多,所以喜欢用啥就用啥(大实话,虽然也是废话)。语法上的差别虽然有那么一点,大部分是syntax sugar,我斗胆稍微列几个(python我也忘得差不多了,不对的大家尽管来鞭尸吧),但是主要差异还是设计思想上的:灵活vs明确. 我不认为两者在生产力上会有什么差别,如果你熟悉的话。*注意,仅限语言本身的比较。
1. ruby的case可以匹配很多东西:范围/数组,对象,正则表达,python没有case/switch而使用if/else比较死板点
2. python的缩进很漂亮,虽然有时会造成些许麻烦。ruby的end蛮难看的,所以大家都被逼当one liner(玩笑)
3. 感觉上ruby比python更OO,当然这也可能是因为python不提倡用那些改变对象内部构造的‘伎俩’造成的错觉
4. python有list comprehension, ruby没有:(
5. python有真正的keyword argument, ruby用hash模拟,当然实际用起来没什么差别
6. python的self很讨厌,ruby没有那种繁琐的东西
7. reflection,ruby内置了很多方法,比如object.methods,而python把这些信息存在特殊的字典里。差不多
8. ruby的block功能很强,python的lambda只能返回单一值
9. ruby的open class已经声明远播,可以玩出2.days.ago这样的花样,python好像没法直接修改内置类也反对这么做。
10. python需要用@classmethod修饰声明类方法,ruby是内建
11. ruby有单子方法,也就对对象单独定制,python不知道有没有类似概念
12. ruby有method_missing机制,python可以使用__getattr__截获未定义方法(from qiezi)
13. ruby使用单继承+mixin,python使用多重继承,不过python也有mixin
14. ruby有attr_*系列语法helper,省却自己写一堆setter/getter, python的property方法还是得自己写setter/getter
15. ruby和python都使用duck typing,不过python也有一套显式的interface机制(从zope3并入内核了么?)
16. ruby的函数调用括号是可省的,稍微少敲几下键盘。python默认没括号也不带参数的话返回函数本身的一个引用。
17. 我不清楚python的meta programming能到什么程度,只好等大牛来说说了。只是觉得pythoner不常用那个,也许觉得会把程序逻辑搞得晦涩不明。
18. ruby从perl继承了一部分难看的东西,比如很多预定义的$x常量
19. ruby内建正则表达,方便一点
20. ruby的yield是用来call block的。而python的yield是用来给generator输入输出值的。
21. python的库给我感觉命名规范有点不统一,有些方法用snake_case有些则用CamelCase,也许是库太多了遗留下的历史问题
22. python的三引号很漂亮,ruby的<<-XX...XX太难看了,也可以用%q{...}包裹多行文字(from qiezi)
23. ruby的类库设计中喜欢给方法添加别名,方便记忆。
另: ruby官方网站也提供了一些基本的比较。(from Robbin)
评论
charon
2007-01-29
imagex 写道
性能方面,Python比Ruby要好,但两者都是动态语言,都好不到哪里去,所以打平。非要追求很高的性能的话,两者都不能用。
虽然都是动态语言,但是性能上还是有差异的。ruby比python慢个3-5倍,在没优化时如此,优化(当然不是优化算法,而是使用psyco或yarv之类的)之后还是差不多。
所以并不是打平,有个哥们就是因为这个原因从rails转向到django. http://reddit.com/user/jesusphreak/
引用
语法和思想方面,Ruby优于Python,Python的self,不去写一个大一点的程序是不知道的,初始化的函数里面每一行几乎都要self下,用的时候再self下,我记得当初放弃Python很大的一个原因,就是因为某些语法的不可容忍。
hehe.这个就不知道了。
我当初选择python,也就是因为它严格/显式的语法.比如self,当初写C++/java程序时,只有在引起混淆的时候才写this,属于可选项,发生问题时最后也不知道到底是漏写了还是怎么着另有深意.现在强制如此,代码读起来爽多了.
引用
但再看看google trends里面吧,其实Ruby已经超越了Python,当然比较的时候,请记得加上rails,django等,这样就比较明显了。
这句话,不客气地说就是扯淡.
客气的说,应该改成: rails已经超越了django. 但说句实话,rails一直在django之前,所以是句废话.
至于python和ruby,真实趋势如何不了解,但是google上的,很容易查:
http://www.google.com/trends?q=python+programming%2Cruby+programming
不需要加什么rails,django之类的. 否则比较的是框架,而不是语言本身.
imagex
2007-01-29
Ruby很多地方要比Python高明,毕竟matz在写Ruby的时候,是站在Python的肩膀上的。
性能方面,Python比Ruby要好,但两者都是动态语言,都好不到哪里去,所以打平。非要追求很高的性能的话,两者都不能用。
语法和思想方面,Ruby优于Python,Python的self,不去写一个大一点的程序是不知道的,初始化的函数里面每一行几乎都要self下,用的时候再self下,我记得当初放弃Python很大的一个原因,就是因为某些语法的不可容忍。
成熟度方面,Python优于Ruby,Python发展的时间比Ruby长,所以社区比较成熟,有很多成熟的应用,比如豆瓣这样的,或许这就是我们争论的很大一个原因,Ruby比Python发展的时间少很多,这是大家比较的时候忽略的一点。但再看看google trends里面吧,其实Ruby已经超越了Python,当然比较的时候,请记得加上rails,django等,这样就比较明显了。Ruby在Windows上很不成熟,这说明什么?这说明Ruby还有很大的上升空间,因为并不是Ruby做不到,而是还欠火候,而Python的上升空间已经相对很小了。
性能方面,Python比Ruby要好,但两者都是动态语言,都好不到哪里去,所以打平。非要追求很高的性能的话,两者都不能用。
语法和思想方面,Ruby优于Python,Python的self,不去写一个大一点的程序是不知道的,初始化的函数里面每一行几乎都要self下,用的时候再self下,我记得当初放弃Python很大的一个原因,就是因为某些语法的不可容忍。
成熟度方面,Python优于Ruby,Python发展的时间比Ruby长,所以社区比较成熟,有很多成熟的应用,比如豆瓣这样的,或许这就是我们争论的很大一个原因,Ruby比Python发展的时间少很多,这是大家比较的时候忽略的一点。但再看看google trends里面吧,其实Ruby已经超越了Python,当然比较的时候,请记得加上rails,django等,这样就比较明显了。Ruby在Windows上很不成熟,这说明什么?这说明Ruby还有很大的上升空间,因为并不是Ruby做不到,而是还欠火候,而Python的上升空间已经相对很小了。
笨笨狗
2006-10-13
njmzhang 写道
对我来说,Python不爽的地方更多,
没有?:表达式我就觉得不方便,dive-in-python书上用的1 and a or b这个技巧实在难看
没有?:表达式我就觉得不方便,dive-in-python书上用的1 and a or b这个技巧实在难看
2.5里,可以这么写:
a if expression else b
如果expression为True则返回a,否则返回b,感觉还是很自然的啊……
charon
2006-10-11
确实方法的bound,unbound带来了一些很微妙的东西
python采用了偏向函数的方式来解决这个问题,相对一致一些,但是理解上会带来一些困惑.不过类方法声明中的那个第一个参数self即便没有也可以通过上下文在编译期或运行期推断出来的,但好像为了显式哲学这个self还会流传下去.
ruby干脆一拍两散,倒也干净
python采用了偏向函数的方式来解决这个问题,相对一致一些,但是理解上会带来一些困惑.不过类方法声明中的那个第一个参数self即便没有也可以通过上下文在编译期或运行期推断出来的,但好像为了显式哲学这个self还会流传下去.
ruby干脆一拍两散,倒也干净
cookoo
2006-10-11
charon 写道
这个用上__slots__就可以了。
但是说到这类打字错误,python和ruby都是难兄难弟,ruby不比python强一点,也不会弱。都需要靠单元测试来确定这类错误,属于50步 vs 50步.
确实如此,哈哈刚发现你原来的代码里就有个typo: 最后那个reporducer
def simple_reproducer_factory():
def reproducer(seeds,gametes):
......
return children
reproducer.times_of_length = 1
return reporducer
引用
还是有重要差别的,首先那个simple_reproducer_factory是一个顶级的函数,不在任何class里面,其次这个reproducer也是一个函数,这两个家伙都不是方法. 但是对于函数对象,还可以往上添加属性.
前面说的不够OO主要是指这个意思,使我不必再纠缠在class的世界里面。
ruby和python一样,也是有top level函数的,不用空造个类包装一下。函数也能直接当参数传来传去,所谓first class对象。但是差别确实是有的:ruby的method默认会绑定到对象上去,所以即使是top level声明的method, 实际已经隐式地绑定到self上去了。相反,python的method默认不邦定,所以当作为实例方法的时候需要显式地传self进去绑定。
正因为这样ruby提供了不需要绑定的proc:
p = proc {|x| puts x}
p.better_accessor :test => 1
p.test #=> 1
而method无论是否top level,不能直接这么用,需要‘去绑定’之后获得单独的Method对象才能用:
def foo(n) puts n; end foo.better_accessor :bar => 1 # ArgumentError: wrong number of arguments (0 for 1) f = self.method :foo # => #<Method: Object#foo> f.better_accessor :bar => 1
所以更正一下前面我自己说的:像你python代码那样直接内建一个method再传出来在ruby里要绕弯路,改成内建一个proc再传出来。
charon
2006-10-11
njmzhang 写道
[b,a][?]不是shortcut的
是啊。所以这个也会出现非常有意思的问题,如:
c = a != 0 and b/a or MAX_INT
就不能转换成
[0,b/a][a != 0]
python在这里确实很不爽。不同的idiom方法只能用于不同的场景,极端情况下还是需要用if/else搞定
不过2.5以后就可以直接用
c = b / a if a !=0 else MAX_INT
charon
2006-10-11
ajoo 写道
cookoo 写道
1. well...python还没block呢
lambda不就是block?为什么说没有?
python里面的lambda比block弱一些,只能是表达式
python2.5里面有一个类似的with语句,同样秉承python的显式处理哲学,所以使用起来比block有限制,同时也罗嗦一点点.
其实简单得block,在python里面直接用list comprehension就能搞定,可读性显然大于用block的办法
如:
cy = [ x for x in cx if x > 5 ]
表示cy是cx序列中所有>5的元素的集合
charon
2006-10-11
cookoo 写道
这个例子蛮有说服力的,我以前总认为python那样随时能用obj.new_attr = xx的prototype OO风格添加新属性的方法比较危险,万一碰到手误打错字很郁闷。
这个用上__slots__就可以了。
但是说到这类打字错误,python和ruby都是难兄难弟,ruby不比python强一点,也不会弱。都需要靠单元测试来确定这类错误,属于50步 vs 50步.
引用
“太过OO“的Ruby虽然不能直接支持这么干,不过用点meta programming魔法就可以了,参见以前和ajoo讨论后我写的blog。这样在ruby里就写成
reproducer.better_accessor :times_of_length => 1
还是有重要差别的,首先那个simple_reproducer_factory是一个顶级的函数,不在任何class里面,其次这个reproducer也是一个函数,这两个家伙都不是方法. 但是对于函数对象,还可以往上添加属性.
前面说的不够OO主要是指这个意思,使我不必再纠缠在class的世界里面。
ajoo
2006-10-11
cookoo 写道
1. well...python还没block呢
lambda不就是block?为什么说没有?
njmzhang
2006-10-11
[b,a][?]不是shortcut的
charon
2006-10-11
njmzhang 写道
对我来说,Python不爽的地方更多,
没有?:表达式我就觉得不方便,dive-in-python书上用的1 and a or b这个技巧实在难看
没有?:表达式我就觉得不方便,dive-in-python书上用的1 and a or b这个技巧实在难看
2.5 里面有一个和ruby差不多的if/else赋值语句,和?:差不多了
1 and a or b还是比较少用的,应为a必须为真值,一般都是[b,a][?]这样的做法
njmzhang
2006-10-11
对我来说,Python不爽的地方更多,
没有?:表达式我就觉得不方便,dive-in-python书上用的1 and a or b这个技巧实在难看
没有?:表达式我就觉得不方便,dive-in-python书上用的1 and a or b这个技巧实在难看
cookoo
2006-10-11
罪过罪过,刚才忘了用永久链接了。
ajoo
2006-10-11
blog不存在
cookoo
2006-10-11
charon 写道
其实我觉得python最爽的地方就是终于不用太OO了。
以前玩java的时候明明只需要一个辅助性函数,却非得搞一个helper类,策略模式的实现也是类飞来飞去的。
在python里面,我这样写一个工厂:
因为函数实际上也是对象,可以有自己的属性,所以有些东西就不需要用到静态变量或者全局变量,直接当作属性好了。 简直帅呆了.........
但是我对ruby了解不多,不好说。
以前玩java的时候明明只需要一个辅助性函数,却非得搞一个helper类,策略模式的实现也是类飞来飞去的。
在python里面,我这样写一个工厂:
def simple_reproducer_factory():
def reproducer(seeds,gametes):
......
return children
reproducer.times_of_length = 1
return reporducer
因为函数实际上也是对象,可以有自己的属性,所以有些东西就不需要用到静态变量或者全局变量,直接当作属性好了。 简直帅呆了.........
但是我对ruby了解不多,不好说。
这个例子蛮有说服力的,我以前总认为python那样随时能用obj.new_attr = xx的prototype OO风格添加新属性的方法比较危险,万一碰到手误打错字很郁闷。“太过OO“的Ruby虽然不能直接支持这么干,不过用点meta programming魔法就可以了,参见以前和ajoo讨论后我写的blog。这样在ruby里就写成
reproducer.better_accessor :times_of_length => 1
BTW, python2.5偶还没研究过啊,没时间了。。。
qutr
2006-10-11
6. python的self很讨厌,ruby没有那种繁琐的东西
-------
self写惯了也就成自然了。
-------
self写惯了也就成自然了。
charon
2006-10-11
ajoo 写道
我说几个ruby让我不爽的地方,pythoner来说说python是不是更好
1。block/proc的区别。概念冗余。而且造成meta-code写起来有障碍。python是不是只有lambda?
2。require不是像java的import一样只输入符号表,而是执行一个文件。更象c的#include。而且require还不能有效检查两个文件是否相同。
3。没有包私有概念。
4。没有一个module loader的概念。一个库的文件之间依赖,还要写require 'mylibname/filename'。这个mylibname很别扭。
5。string不是unicode的。
6。string是mutable的。
1。block/proc的区别。概念冗余。而且造成meta-code写起来有障碍。python是不是只有lambda?
2。require不是像java的import一样只输入符号表,而是执行一个文件。更象c的#include。而且require还不能有效检查两个文件是否相同。
3。没有包私有概念。
4。没有一个module loader的概念。一个库的文件之间依赖,还要写require 'mylibname/filename'。这个mylibname很别扭。
5。string不是unicode的。
6。string是mutable的。
python中import也是执行一个文件,但是只是在第一次被import的时候才执行(不过这个执行只是模块级全局变量的赋值,如顶级的函数/类定义),其后的因为可以在全局符号表找到,所以不需要执行了(除非显式reload). 这个动作其实和java类被第一次load的时候得动作类似
其实我觉得python最爽的地方就是终于不用太OO了。
以前玩java的时候明明只需要一个辅助性函数,却非得搞一个helper类,策略模式的实现也是类飞来飞去的。
在python里面,我这样写一个工厂:
def simple_reproducer_factory():
def reproducer(seeds,gametes):
......
return children
reproducer.times_of_length = 1
return reporducer
因为函数实际上也是对象,可以有自己的属性,所以有些东西就不需要用到静态变量或者全局变量,直接当作属性好了。 简直帅呆了.........
但是我对ruby了解不多,不好说。
charon
2006-10-11
cookoo 写道
4. 这个python也没有,比如lib/disutils/util.py的开头:
import sys, os, string, re from distutils.errors import DistutilsPlatformError from distutils.dep_util import newer from distutils.spawn import spawn from distutils import log
原因同2,因为文件和类不统一,目录和命名域不匹配。某种程度上ruby的require其实管理的是命名域搜索路径而不是命名域本身。极端情况下你可以在不同位置的文件里建立同一命名域下的内容,然后同时require这两个文件结构得到同一个命名域下的东西。我觉得python应该有可能‘感知’同一目录下的别的文件而不用去看一个全局的搜索路径,而ruby很难这么做。
2.5之前,对于同一目录里面的文件依赖,python是可以省去distutils的,只是不建议而已,因为写了distutils就更加明确了这个模块的由来.
python2.5之后正式引入了相对import,在概念上把饼画圆了。
但是对不同搜索路径下的多个相同命名树,python不会像java一样从多个位置加载,而只是加载第一个位置,后面的被直接无视.
cookoo
2006-10-11
我现在觉得ruby最郁闷的地方是扩展不方便啊。python有pyrex, ctypes,扩展和包装别的c库都很爽啊。
cookoo
2006-10-11
ajoo 写道
我说几个ruby让我不爽的地方,pythoner来说说python是不是更好
1。block/proc的区别。概念冗余。而且造成meta-code写起来有障碍。python是不是只有lambda?
2。require不是像java的import一样只输入符号表,而是执行一个文件。更象c的#include。而且require还不能有效检查两个文件是否相同。
3。没有包私有概念。
4。没有一个module loader的概念。一个库的文件之间依赖,还要写require 'mylibname/filename'。这个mylibname很别扭。
5。string不是unicode的。
6。string是mutable的。
1。block/proc的区别。概念冗余。而且造成meta-code写起来有障碍。python是不是只有lambda?
2。require不是像java的import一样只输入符号表,而是执行一个文件。更象c的#include。而且require还不能有效检查两个文件是否相同。
3。没有包私有概念。
4。没有一个module loader的概念。一个库的文件之间依赖,还要写require 'mylibname/filename'。这个mylibname很别扭。
5。string不是unicode的。
6。string是mutable的。
1. well...python还没block呢
2. python的import是比require自然点,它能理解a.b.c代表嵌套目录,也能用from..import..从一个文件里引入一部分。但总体上python和ruby都不要求一个文件一个类,相比java来说就不需要深度嵌套的目录结构,python的命名域和目录结构之间的关系比ruby更协调自然,而ruby的require和命名域是独立的,可以搞得很复杂。
3. 包私有...ruby可以在module里用private/protected。。。python有个下划线文件名约定,估计是目录中的私有文件吧。
4. 这个python也没有,比如lib/disutils/util.py的开头:
import sys, os, string, re from distutils.errors import DistutilsPlatformError from distutils.dep_util import newer from distutils.spawn import spawn from distutils import log
原因同2,因为文件和类不统一,目录和命名域不匹配。某种程度上ruby的require其实管理的是命名域搜索路径而不是命名域本身。极端情况下你可以在不同位置的文件里建立同一命名域下的内容,然后同时require这两个文件结构得到同一个命名域下的东西。我觉得python应该有可能‘感知’同一目录下的别的文件而不用去看一个全局的搜索路径,而ruby很难这么做。
5. 这个可以加$KCODE = 'u'; require 'jcode' 让ruby把string按unicode对待。不过字符串函数还是有问题,最新的rails开发版本有个核心库补丁解决了这个问题,不知道多久才会并入核心库。
- 浏览: 319013 次
- 性别:

- 来自: Montreal

- 详细资料
搜索本博客
我的相册
20059805856241
共 10 张
共 10 张
最新评论
-
Darcs简介
good 3x
-- by 夜鸣猪 -
Pratical Ocaml作者采访
现在主要用F#分析数据,因为比较舒服(人懒啊)。其实也只用到很少的FP特性,Ru ...
-- by cookoo -
Pratical Ocaml作者采访
一年多了,呵呵,cookoo能说说看,学习使用OCaml的进展和体会吗?
-- by billgui -
Memory - 柿岛伸次
还不错啊。
-- by hazzy -
Memory - 柿岛伸次
我很想下这个,可就是不能下。LZ能否提供链接
-- by yeshucheng






评论排行榜