旁觀者清 Python與Ruby各有千秋
原創(chuàng)【51CTO獨家特稿】關(guān)于Ruby和Python之間的對比在網(wǎng)上有太多的口水,但我卻沒有發(fā)現(xiàn)真正有用的討論,因為大家總是圍繞雙方的功能差異進(jìn)行爭辯,這樣下去顯得毫無意義,其實該有的雙方都會有,要不然有一方肯定早已被另一方消滅。
51CTO推薦閱讀:Python線程編程比Ruby應(yīng)用的優(yōu)點
雖然我個人更喜歡Python,但并不代表Python就比Ruby功能要多,要比Ruby強大,也無法教唆其他人也跟我一樣選擇Python,因為每個人的口味都不一樣。因此,客觀地列出雙方的不同點能夠有效地避免大量的口水之爭,注意我們不談?wù)Z法上的差異,那完全沒有意思,另外,如果你覺得本文列出的項目有帶有主觀色彩的,你也可以談?wù)勀愕目捶ā?/p>
Ruby在類主體中有類引用
在Ruby中,你可以引用類主體中的類(self),在Python中就不行。Ruby代碼示例:
- class Kaka
- puts self
- end
這里的self是一個類,上面這串代碼將會輸出“KaKa”,在Python中,沒有辦法輸出類名或從類定義主體中訪問類。
Ruby中的所有類都是可變的
它允許你為核心類開發(fā)擴展,下面是一個rails擴展示例:
- class String
- def starts_with?(other)
- head = self[0, other.length]
- head == other
- end
- end
Python(假設(shè)沒有’’.startwith方法):
- def starts_with(s, prefix):
- return s[:len(prefix)] == prefix
你可以在任何序列(不只是字符串)上使用它,但必須明確地導(dǎo)入它,如:
- from some_module import starts_with
Ruby有類似Perl的腳本功能
Ruby有一個regexps類,$-變量,awk/perl逐行輸入循環(huán)和其它功能使它更適合編寫小型shell腳本。
Ruby有類延續(xù)
Ruby有這個特性都是得益于callcc語句。在Python中,你可以用多種不同的技術(shù)創(chuàng)建延續(xù),但語音本身并沒有內(nèi)置支持這項特性。
Ruby有塊
使用do語句,你可以在Ruby中創(chuàng)建多行匿名函數(shù),它將會作為一個參數(shù)傳遞給do前面的方法。在Python中,你可以傳遞一個方法或使用發(fā)生器實現(xiàn)同樣的目的。
- Ruby:
- amethod { |here|
- many=lines+of+code
- goes(here)
- }
Python(Ruby塊與Python中不同的構(gòu)造對應(yīng)):
- 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中調(diào)用塊的語句叫做“yield”,在Python中它將創(chuàng)建一個發(fā)生器。
Ruby:
- def themethod
- yield 5
- end
- themethod do |foo|
- puts foo
- end
Python:
- def themethod():
- yield 5
- for foo in themethod():
- print foo
雖然原理不一樣,但結(jié)果非常類似的。
Ruby支持更容易的功能性編程(管道式)
- myList.map(&:description).reject(&:empty?).join("\n")
Python:
- descriptions = (f.description() for f in mylist)
- "\n".join(filter(len, descriptions))
#p#
Python內(nèi)置有發(fā)生器(和Ruby中的塊用法類似)
Python支持發(fā)生器,在Ruby中,你也可以使用發(fā)生器模塊,但要使用延續(xù)從一個塊創(chuàng)建一個發(fā)生器,或者使用塊/proc/lambda,此外,Ruby 1.9中的纖程(Fibers)也可以作為發(fā)生器使用。docs.python.org提供了發(fā)生器示例:
- def reverse(data):
- for index in range(len(data)-1, -1, -1):
- yield data[index]
請與上面的塊示例代碼對比。
Python有靈活的命名空間處理方法
在Ruby中,當(dāng)你使用require導(dǎo)入一個文件時,文件中定義的所有項目將會在你的全局命名空間中結(jié)束,這會導(dǎo)致命名空間污染,解決辦法是Ruby模塊,但如果你使用模塊創(chuàng)建了一個命名空間,你必須使用該命名空間訪問包含的類。
在Python中,文件也是一個模塊,你可以使用“from themodule import *”導(dǎo)入它包含的名字,雖然這樣也會污染命名空間,但可以使用“from themodule import aname, another”或簡單地“import themodule”導(dǎo)入選擇的名字,然后使用“themodule.aname”訪問名字。
Python有文檔字符串(docstrings)
文檔字符串是附加到模塊、函數(shù)和方法的字符串,它有助于創(chuàng)建幫助命令和自動化文檔。
- 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的“方法#源位置”從文件檢索。
Python有更多的庫
Python有大量的模塊和綁定的庫。
Python有多重繼承
Ruby沒有多重繼承。它作為抽象類類型重復(fù)使用模塊。
Python有列表/字典理解能力
Python:
- res = [x*x for x in range(1, 10)]
Ruby :
- res = (0..9).map { |x| x * x }
Python:
- >>> (x*x for x in range(10))
- <generator object <genexpr> at 0xb7c1ccd4>
- >>> list(_)
- [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Ruby:
- 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'}
Ruby:
- >> Hash[{1=>2, 3=>4}.map{|x,y| [x,(y*y).to_s]}]
- => {1=>"4", 3=>"16"}
Python有裝飾器
與Ruby中創(chuàng)建的裝飾器類似,但Ruby中的裝飾器不像Python中那樣重要,它是非必需的。
原文作者:Lennart Regebro
原文名:What does Ruby have that Python doesn’t, and vice versa?
原文地址:http://stackoverflow.com/questions/1113611/what-does-ruby-have-that-python-doesnt-and-vice-versa
【編輯推薦】
- Python編程語言與Ruby之間的比較
- 捕捉Ruby正則表達(dá)式用法精髓
- Python等動態(tài)語言企業(yè)應(yīng)用面面觀
- Python線程編程比ruby應(yīng)用的優(yōu)點