網絡上python和ruby之間的口水戰從來都沒有停止過。有人說python慢,有人說ruby更慢;有人說python美,有人說ruby更美。究竟怎樣呢?
我們不搞大而全的測評,就從簡單的N皇后問題求方法數的暴力搜索程序中窺探一下吧:
下面是代碼:
1 N=13 2 col=[0]*N 3 d1=[0]*(N*2) 4 d2=[0]*(N*2) 5 ret=0 6 def dfs(x): 7 global ret 8 if x==N: 9 ret+=1 10 else: 11 for i in xrange(N): 12 if col[i]==0 and d1[i+x]==0 and d2[i-x+N]==0: 13 col[i],d1[i+x],d2[i-x+N]=1,1,1 14 dfs(x+1) 15 col[i],d1[i+x],d2[i-x+N]=0,0,0 16 dfs(0) 17 print ret
根據python代碼,我改編了各個語言的版本:

1 N=13 2 $col=[0]*N 3 $d1=[0]*(N*2) 4 $d2=[0]*(N*2) 5 $ret=0 6 def dfs(x) 7 if x==N 8 $ret+=1 9 else 10 N.times do |i| 11 if $col[i]==0 and $d1[i+x]==0 and $d2[i-x+N]==0 12 $col[i]=$d1[i+x]=$d2[i-x+N]=1 13 dfs x+1 14 $col[i]=$d1[i+x]=$d2[i-x+N]=0 15 end 16 end 17 end 18 end 19 dfs 0 20 puts $ret

1 #include <cstdio> 2 using namespace std; 3 const int N=13; 4 int col[N],d1[N+N],d2[N+N]; 5 int ret=0; 6 void dfs(int x){ 7 if (x==N) 8 ret++; 9 else{ 10 for (int i=0;i<N;i++) 11 if (col[i]==0 && d1[i+x]==0 && d2[i-x+N]==0){ 12 col[i]=d1[i+x]=d2[i-x+N]=1; 13 dfs(x+1); 14 col[i]=d1[i+x]=d2[i-x+N]=0; 15 } 16 } 17 } 18 int main() 19 { 20 dfs(0); 21 printf("%d\n",ret); 22 return 0; 23 }

1 package main 2 import "fmt" 3 const N=13 4 var col [N]int 5 var d1,d2 [N*2]int 6 var ret int 7 func dfs(x int){ 8 if x==N{ 9 ret++ 10 }else{ 11 for i:=0;i<N;i++ { 12 if col[i]==0 && d1[i+x]==0 && d2[i-x+N]==0 { 13 col[i],d1[i+x],d2[i-x+N]=1,1,1 14 dfs(x+1) 15 col[i],d1[i+x],d2[i-x+N]=0,0,0 16 } 17 } 18 } 19 } 20 func main(){ 21 dfs(0) 22 fmt.Println(ret) 23 }
下面是代碼長度的比較:
268 a.py
273 a.rb
333 a.go
356 a.cpp
可以看出,python是最短的,而ruby其實在某些地方上寫的更短(例如省略了小括號和冒號),但是倒霉的$和end的使用讓它的代碼長度激增。python的縮進政策一方面簡化了end的輸入,另一方面也強制程序員寫出優雅的代碼。不過我至今也想不明白為什么python非要有那個冒號不可。
N.times do |i| if $col[i]==0 and $d1[i+x]==0 and $d2[i-x+N]==0 $col[i]=$d1[i+x]=$d2[i-x+N]=1 dfs x+1 $col[i]=$d1[i+x]=$d2[i-x+N]=0 end end
for i in xrange(N): if col[i]==0 and d1[i+x]==0 and d2[i-x+N]==0: col[i],d1[i+x],d2[i-x+N]=1,1,1 dfs(x+1) col[i],d1[i+x],d2[i-x+N]=0,0,0
go和cpp也是難分長短的。go在函數的主要邏輯的部分幾乎和腳本語言一樣,
func dfs(x int){ if x==N{ ret++ }else{ for i:=0;i<N;i++ { if col[i]==0 && d1[i+x]==0 && d2[i-x+N]==0 { col[i],d1[i+x],d2[i-x+N]=1,1,1 dfs(x+1) col[i],d1[i+x],d2[i-x+N]=0,0,0 } } } }
除了那個煞風景的int,我們很難把他稱作是靜態類型的編譯執行語言。
但go的問題和cpp一樣,那就是,為了讓一個程序運行你不得不說很多“廢話”。
package main import "fmt" #include <cstdio> using namespace std;
然后就是大家十分關心的運行效率了
我time了一下:
python 0m6.944s
ruby 0m6.728s
C(C++) 0m0.360s
go 0m0.320s
這個結果出乎很多人的預料,go竟然可以跑的比c++還快,而python和ruby之間也沒有想象中的性能差距。
當然了,python有一個加速方法,就是使用pypy,而C++也可以開-O2,我們看看效果:
pypy 0m0.908s
C(C++)-O2 0m0.236s
可以看出,增強版的python和go還是領先他們的對手一大截的。
而go為了編譯效率,不強調編譯優化的使用。ruby也有jit工具,不過我還沒有進行測試。
做個總結吧,python和ruby實在是難分高下,更多的是個人的口味問題。
就像唯物主義者和唯心主義者永遠不可能在物質是否決定意識上達成一致一樣,python和ruby的使用者也很難說服對方轉換陣營。更多的爭吵其實只是浪費能量。
如果你不在乎20倍左右的運行時間的差異,那么腳本語言是你的不二選擇,因為他能夠換取你的編碼時間。