Có rất nhiều cuộc thảo luận về Python vs Ruby, và tất cả tôi đều thấy chúng hoàn toàn không có ích gì, bởi vì tất cả chúng đều xoay quanh lý do tại sao tính năng X hút ngôn ngữ Y, hoặc ngôn ngữ tuyên bố Y không có X, mặc dù thực tế nó có. Tôi cũng biết chính xác lý do tại sao tôi thích Python, nhưng điều đó cũng chủ quan và sẽ không giúp bất kỳ ai lựa chọn, vì họ có thể không có cùng sở thích phát triển như tôi.
Do đó, sẽ rất thú vị khi liệt kê sự khác biệt, một cách khách quan. Vì vậy, không có "lambdas của Python hút". Thay vào đó giải thích những gì lambdas của Ruby có thể làm mà Python không thể. Không chủ quan. Mã ví dụ là tốt!
Xin vui lòng không có một số khác biệt trong một câu trả lời. Và bỏ phiếu cho những người bạn biết là chính xác, và xuống những người bạn biết là không chính xác (hoặc chủ quan). Ngoài ra, sự khác biệt trong cú pháp là không thú vị. Chúng ta biết Python làm với thụt đầu dòng những gì Ruby làm với dấu ngoặc và kết thúc và @ đó được gọi là self trong Python.
CẬP NHẬT: Đây hiện là một wiki cộng đồng, vì vậy chúng tôi có thể thêm những khác biệt lớn ở đây.
Ruby có một tài liệu tham khảo lớp trong cơ thể lớp
Trong Ruby, bạn có một tham chiếu đến lớp (tự) đã có trong thân lớp. Trong Python bạn không có một tham chiếu đến lớp cho đến khi việc xây dựng lớp kết thúc.
Một ví dụ:
class Kaka
puts self
end
trong trường hợp này là lớp và mã này sẽ in ra "Kaka". Không có cách nào để in tên lớp hoặc theo các cách khác truy cập lớp từ thân định nghĩa lớp trong Python (định nghĩa phương thức bên ngoài).
Tất cả các lớp đều có thể thay đổi trong Ruby
Điều này cho phép bạn phát triển các phần mở rộng cho các lớp cốt lõi. Dưới đây là ví dụ về tiện ích mở rộng đường ray:
class String
def starts_with?(other)
head = self[0, other.length]
head == other
end
end
Python (hãy tưởng tượng không có ''.startswith
phương pháp nào ):
def starts_with(s, prefix):
return s[:len(prefix)] == prefix
Bạn có thể sử dụng nó trên bất kỳ chuỗi nào (không chỉ chuỗi). Để sử dụng nó, bạn nên nhập nó một cách rõ ràng , vd from some_module import starts_with
.
Ruby có các tính năng kịch bản giống như Perl
Ruby có regexps hạng nhất, $ -variabled, dòng awk / perl theo vòng lặp đầu vào dòng và các tính năng khác phù hợp hơn để viết các tập lệnh shell nhỏ có thể nghiền các tệp văn bản hoặc hoạt động như mã keo cho các chương trình khác.
Ruby có sự tiếp nối hạng nhất
Nhờ tuyên bố callcc. Trong Python, bạn có thể tạo các phần tiếp theo bằng nhiều kỹ thuật khác nhau, nhưng không có sự hỗ trợ nào được tích hợp trong ngôn ngữ.
Ruby có khối
Với câu lệnh "do", bạn có thể tạo một hàm ẩn danh nhiều dòng trong Ruby, hàm này sẽ được truyền vào dưới dạng đối số vào phương thức phía trước do và được gọi từ đó. Trong Python, thay vào đó bạn sẽ làm điều này bằng cách truyền một phương thức hoặc với các trình tạo.
Ruby:
amethod { |here|
many=lines+of+code
goes(here)
}
Python (khối Ruby tương ứng với các cấu trúc khác nhau trong Python):
with amethod() as here: # `amethod() is a context manager
many=lines+of+code
goes(here)
Hoặc là
for here in amethod(): # `amethod()` is an iterable
many=lines+of+code
goes(here)
Hoặc là
def function(here):
many=lines+of+code
goes(here)
amethod(function) # `function` is a callback
Thật thú vị, câu lệnh tiện lợi trong Ruby để gọi một khối được gọi là "suất", trong Python sẽ tạo ra một trình tạo.
Ruby:
def themethod
yield 5
end
themethod do |foo|
puts foo
end
Con trăn
def themethod():
yield 5
for foo in themethod():
print foo
Mặc dù các nguyên tắc là khác nhau, kết quả là rất giống nhau.
Ruby hỗ trợ lập trình kiểu chức năng (giống như ống) dễ dàng hơn
myList.map(&:description).reject(&:empty?).join("\n")
Con trăn
descriptions = (f.description() for f in mylist)
"\n".join(filter(len, descriptions))
Python có các trình tạo tích hợp (được sử dụng như các khối Ruby, như đã lưu ý ở trên)
Python có hỗ trợ cho các trình tạo ngôn ngữ. Trong Ruby 1.8, bạn có thể sử dụng mô-đun trình tạo sử dụng các phần tiếp theo để tạo trình tạo từ một khối. Hoặc, bạn chỉ có thể sử dụng một khối / Proc / lambda! Hơn nữa, trong Ruby 1.9 Fibre, và có thể được sử dụng như là các trình tạo và lớp Enumerator là một trình tạo 4 tích hợp
docs.python.org có ví dụ về trình tạo này:
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
Tương phản điều này với các ví dụ khối ở trên.
Python có khả năng xử lý không gian tên linh hoạt
Trong Ruby, khi bạn nhập tệp với require
, tất cả những thứ được xác định trong tệp đó sẽ kết thúc trong không gian tên toàn cầu của bạn. Điều này gây ra ô nhiễm không gian tên. Giải pháp cho điều đó là các mô-đun Rubys. Nhưng nếu bạn tạo một không gian tên bằng một mô-đun, thì bạn phải sử dụng không gian tên đó để truy cập các lớp được chứa.
Trong Python, tệp là một mô-đun và bạn có thể nhập tên chứa trong from themodule import *
đó, do đó gây ô nhiễm không gian tên nếu bạn muốn. Nhưng bạn cũng có thể nhập tên chỉ được chọn với from themodule import aname, another
hoặc bạn có thể chỉ cần import themodule
truy cập vào tên đó themodule.aname
. Nếu bạn muốn có nhiều cấp độ hơn trong không gian tên của mình, bạn có thể có các gói, đó là các thư mục với các mô-đun và một __init__.py
tệp.
Python có tài liệu
Tài liệu là các chuỗi được gắn vào các mô-đun, chức năng và phương thức và có thể được hướng nội khi chạy. Điều này giúp cho việc tạo ra những thứ như lệnh trợ giúp và tài liệu tự động.
def frobnicate(bar):
"""frobnicate takes a bar and frobnicates it
>>> bar = Bar()
>>> bar.is_frobnicated()
False
>>> frobnicate(bar)
>>> bar.is_frobnicated()
True
"""
Tương đương của Ruby tương tự như javadocs và nằm phía trên phương thức thay vì bên trong nó. Chúng có thể được truy xuất trong thời gian chạy từ các tệp bằng cách sử dụng ví dụ Phương thức # source_location của 1.9
Python có nhiều sự kế thừa
Ruby không ("về mục đích" - xem trang web của Ruby, xem tại đây nó được thực hiện như thế nào trong Ruby ). Nó không sử dụng lại khái niệm mô-đun như một loại lớp trừu tượng.
Python có danh sách / đọc chính tả
Con trăn
res = [x*x for x in range(1, 10)]
Ruby:
res = (0..9).map { |x| x * x }
Con trăn
>>> (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 trở lên :
>>> {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 có trang trí
Những thứ tương tự như trang trí cũng có thể được tạo ra trong Ruby và cũng có thể lập luận rằng chúng không cần thiết như trong Python.
Cú pháp khác biệt
Ruby yêu cầu "end" hoặc "}" để đóng tất cả các phạm vi của nó, trong khi Python chỉ sử dụng khoảng trắng. Đã có những nỗ lực gần đây trong Ruby để cho phép khoảng trắng chỉ thụt lề http://github.com/michaeledgar/siền