Tôi sẽ không đăng bài này như một câu trả lời, nhưng Xeoncross đã yêu cầu tôi, vì vậy chúng tôi đi đây:
(Sidenote: nếu ai đó có thể khắc phục sự cố đánh dấu trong ví dụ mã nhỏ, tôi sẽ đánh giá cao nó.)
Erik Max Francis đã viết:
"Brandon J. Van Every" đã viết:
Ruby có gì hay hơn Python? Tôi chắc chắn có một cái gì đó. Nó là gì? Sẽ không có ý nghĩa hơn khi hỏi người Ruby điều này, thay vì người Python?
Có thể, hoặc có thể không, tùy thuộc vào mục đích của một người - ví dụ: nếu mục đích của một người bao gồm "nghiên cứu xã hội học" về cộng đồng Python, thì việc đặt câu hỏi cho cộng đồng đó có khả năng chứng minh nhiều thông tin hơn về nó, hơn là đưa họ ra nơi khác :-). Cá nhân, tôi sẵn sàng nắm lấy cơ hội để theo dõi hướng dẫn Ruby một ngày của Dave Thomas tại OSCON cuối cùng. Bên dưới lớp veneer mỏng về sự khác biệt về cú pháp, tôi thấy Ruby và Python giống nhau một cách đáng kinh ngạc - nếu tôi tính toán cây bao trùm tối thiểu trong số bất kỳ tập hợp ngôn ngữ nào, tôi khá chắc chắn Python và Ruby sẽ là hai lá đầu tiên hợp lại một nút trung gian :-).
Chắc chắn, tôi nhận được mệt mỏi, trong Ruby, gõ ngớ ngẩn "kết thúc" vào cuối mỗi khối (thay vì chỉ unindenting) - nhưng sau đó tôi nhận được để tránh gõ bình đẳng-ngớ ngẩn :
mà Python đòi hỏi ở
sự khởi đầu của mỗi khối, vì vậy đó gần như là một rửa :-). Các khác biệt cú pháp khác như @foo
so với
self.foo
, hoặc tầm quan trọng cao hơn của trường hợp trong Ruby vs Python, thực sự không liên quan đến tôi.
Những người khác không nghi ngờ gì về việc họ lựa chọn ngôn ngữ lập trình cho những vấn đề như vậy và họ tạo ra những cuộc tranh luận sôi nổi nhất - nhưng với tôi đó chỉ là một ví dụ về Luật của Parkinson trong hành động (số tiền tranh luận về một vấn đề tỷ lệ nghịch với vấn đề tầm quan trọng thực tế). Một sự khác biệt về cú pháp mà tôi thấy rất quan trọng và có lợi cho Python - nhưng những người khác chắc chắn sẽ nghĩ ngược lại - là "làm thế nào để bạn gọi một hàm không có tham số". Trong Python (như trong C), để gọi một hàm, bạn luôn áp dụng "toán tử cuộc gọi" - dấu ngoặc đơn ngay sau khi đối tượng bạn đang gọi (bên trong các dấu ngoặc đơn đó đi đến các đối số bạn đang chuyển trong cuộc gọi - nếu bạn đang vượt qua không có đối số, sau đó dấu ngoặc đơn trống). Điều này chỉ đề cập đến bất kỳ đối tượng nào, không có toán tử tham gia, vì nó chỉ là một tham chiếu đến đối tượng - trong bất kỳ bối cảnh nào, không có trường hợp đặc biệt, ngoại lệ, quy tắc đặc biệt và tương tự. Trong Ruby (như trong Pascal), để gọi một hàm VỚI các đối số bạn truyền các đối số (thông thường trong ngoặc đơn, mặc dù đó không phải là trường hợp thường gặp) - NHƯNG nếu hàm không có đối số thì chỉ cần đề cập đến hàm gọi nó. Điều này có thể đáp ứng sự mong đợi của nhiều người (ít nhất, không còn nghi ngờ gì nữa, những người chỉ có kinh nghiệm lập trình trước đó là với Pascal hoặc các ngôn ngữ khác có "gọi điện thoại" tương tự, như Visual Basic) - nhưng đối với tôi, nó có nghĩa là chỉ đề cập đến một đối tượng có thể EITHER có nghĩa là một tham chiếu đến đối tượng, HOẶC một cuộc gọi đến đối tượng, tùy thuộc vào loại đối tượng - và trong những trường hợp tôi không thể tham chiếu đến đối tượng bằng cách chỉ đề cập đến nó, tôi sẽ cần sử dụng rõ ràng "hãy cho tôi một tham chiếu đến điều này, ĐỪNG gọi nó!" toán tử không cần thiết khác. Tôi cảm thấy điều này tác động đến "hạng nhất" của các chức năng (hoặc phương thức hoặc các đối tượng có thể gọi khác) và khả năng trao đổi các đối tượng một cách trơn tru. Do đó, với tôi, sự khác biệt cú pháp cụ thể này là một dấu đen nghiêm trọng đối với Ruby - nhưng tôi hiểu tại sao những người khác lại làm điều khác, mặc dù tôi khó có thể không đồng ý kịch liệt hơn với họ :-). Bên dưới cú pháp, chúng ta có một số khác biệt quan trọng về ngữ nghĩa cơ bản - ví dụ: các chuỗi trong Ruby là các đối tượng có thể thay đổi (như trong C ++), trong khi trong Python chúng không thể thay đổi (như trong Java hoặc tôi tin C #). Một lần nữa, những người đánh giá chủ yếu bởi những gì họ đã quen thuộc có thể nghĩ rằng đây là điểm cộng cho Ruby (trừ khi họ quen thuộc với Java hoặc C #, tất nhiên :-). Tôi, tôi nghĩ rằng các chuỗi bất biến là một ý tưởng tuyệt vời (và tôi không ngạc nhiên khi Java, tôi nghĩ độc lập, đã phát minh lại ý tưởng đã có trong Python), mặc dù tôi cũng không phiền khi có loại "bộ đệm chuỗi có thể thay đổi" (và lý tưởng nhất là dễ sử dụng hơn "bộ đệm chuỗi" của Java); và tôi không đưa ra phán xét này vì sự quen thuộc - trước khi nghiên cứu Java, ngoài các ngôn ngữ lập trình chức năng nơi những người đánh giá chủ yếu bởi những gì họ đã quen thuộc có thể nghĩ rằng đây là điểm cộng cho Ruby (trừ khi họ quen thuộc với Java hoặc C #, tất nhiên :-). Tôi, tôi nghĩ rằng các chuỗi bất biến là một ý tưởng tuyệt vời (và tôi không ngạc nhiên khi Java, tôi nghĩ độc lập, đã phát minh lại ý tưởng đã có trong Python), mặc dù tôi cũng không phiền khi có loại "bộ đệm chuỗi có thể thay đổi" (và lý tưởng nhất là dễ sử dụng hơn "bộ đệm chuỗi" của Java); và tôi không đưa ra phán xét này vì sự quen thuộc - trước khi nghiên cứu Java, ngoài các ngôn ngữ lập trình chức năng nơi những người đánh giá chủ yếu bởi những gì họ đã quen thuộc có thể nghĩ rằng đây là điểm cộng cho Ruby (trừ khi họ quen thuộc với Java hoặc C #, tất nhiên :-). Tôi, tôi nghĩ rằng các chuỗi bất biến là một ý tưởng tuyệt vời (và tôi không ngạc nhiên khi Java, tôi nghĩ độc lập, đã phát minh lại ý tưởng đã có trong Python), mặc dù tôi cũng không phiền khi có loại "bộ đệm chuỗi có thể thay đổi" (và lý tưởng nhất là dễ sử dụng hơn "bộ đệm chuỗi" của Java); và tôi không đưa ra phán xét này vì sự quen thuộc - trước khi nghiên cứu Java, ngoài các ngôn ngữ lập trình chức năng nơi Tôi nghĩ rằng các chuỗi bất biến là một ý tưởng tuyệt vời (và tôi không ngạc nhiên khi Java, tôi nghĩ độc lập, đã phát minh lại ý tưởng đã có trong Python), mặc dù tôi cũng không phiền khi có loại "bộ đệm chuỗi có thể thay đổi" (và lý tưởng với tính dễ sử dụng tốt hơn "bộ đệm chuỗi" của Java); và tôi không đưa ra phán xét này vì sự quen thuộc - trước khi nghiên cứu Java, ngoài các ngôn ngữ lập trình chức năng nơi Tôi nghĩ rằng các chuỗi bất biến là một ý tưởng tuyệt vời (và tôi không ngạc nhiên khi Java, tôi nghĩ độc lập, đã phát minh lại ý tưởng đã có trong Python), mặc dù tôi cũng không phiền khi có loại "bộ đệm chuỗi có thể thay đổi" (và lý tưởng với tính dễ sử dụng tốt hơn "bộ đệm chuỗi" của Java); và tôi không đưa ra phán xét này vì sự quen thuộc - trước khi nghiên cứu Java, ngoài các ngôn ngữ lập trình chức năng nơitất cả dữ liệu là bất biến, tất cả các ngôn ngữ tôi biết đều có chuỗi có thể thay đổi - nhưng khi tôi lần đầu tiên nhìn thấy ý tưởng chuỗi bất biến trong Java (mà tôi đã học tốt trước khi tôi học Python), nó ngay lập tức rất tuyệt vời, phù hợp với tôi ngữ nghĩa tham chiếu của ngôn ngữ lập trình cấp cao hơn (trái ngược với ngữ nghĩa giá trị phù hợp nhất với các ngôn ngữ gần với máy hơn và xa hơn các ứng dụng, như C) với các chuỗi như lớp thứ nhất, tích hợp (và đẹp quan trọng) kiểu dữ liệu.
Ruby có một số lợi thế trong ngữ nghĩa cơ bản - ví dụ, việc loại bỏ "danh sách so với tuples" của Python là sự phân biệt cực kỳ tinh tế. Nhưng chủ yếu là điểm số (như tôi giữ nó, với sự đơn giản là một điểm cộng lớn và sự tinh tế, khéo léo, một điểm trừ đáng chú ý) là chống lại Ruby (ví dụ, có cả hai khoảng thời gian đóng và nửa mở, với các ký hiệu a..b và a .. .b [bất kỳ ai cũng muốn khẳng định rằng đó là điều hiển nhiên đó là gì? -)], thật ngớ ngẩn - IMHO, tất nhiên!). Một lần nữa, những người coi việc có nhiều thứ tương tự nhưng khác biệt một cách tinh tế ở cốt lõi của ngôn ngữ là PLUS, chứ không phải là MINUS, tất nhiên sẽ tính những "cách khác" từ cách tôi đếm chúng :-).
Đừng lầm tưởng bởi những so sánh này khi nghĩ rằng hai ngôn ngữ
rấtkhác nhau, nhớ bạn Họ không. Nhưng nếu tôi được yêu cầu so sánh "capelli d'angelo" với "spaghettini", sau khi chỉ ra rằng hai loại mì ống này không thể phân biệt được với bất kỳ ai và có thể hoán đổi cho nhau trong bất kỳ món ăn nào bạn muốn chuẩn bị, thì tôi chắc chắn sẽ có để chuyển sang kiểm tra bằng kính hiển vi về độ dài và đường kính khác nhau rõ rệt như thế nào, làm thế nào các đầu của sợi được làm thon trong một trường hợp chứ không phải trong trường hợp khác, v.v. - để thử và giải thích tại sao tôi, cá nhân, lại thích có capelli d 'angelo là mì ống trong bất kỳ loại nước dùng nào, nhưng sẽ thích spaghettini hơn là pastasciutta đi kèm với nước sốt thích hợp cho các dạng pasta mỏng dài như vậy (dầu ô liu, tỏi băm, ớt đỏ băm nhỏ, và cá cơm nghiền mịn, ví dụ - nhưng nếu bạn cắt lát tỏi và ớt thay vì băm nhỏ, thì bạn nên chọn phần thân của mì spaghetti chứ không phải là spaghettini mỏng hơn, và sẽ được khuyên nên bỏ qua món achoview và thay vào đó là húng quế tươi [ hoặc thậm chí - Tôi là một kẻ dị giáo ...! - bạc hà nhẹ ...] lá - vào giây phút cuối cùng trước khi phục vụ món ăn). Ooops, xin lỗi, nó cho thấy rằng tôi đang đi du lịch nước ngoài và đã không có mì ống trong một thời gian, tôi đoán. Nhưng sự tương tự vẫn còn khá tốt! -) và sẽ được khuyên nên từ bỏ achoview và thay vào đó là một ít húng quế tươi [hoặc thậm chí - Tôi là một kẻ dị giáo ...! - bạc hà nhẹ ...] lá - vào giây phút cuối cùng trước khi phục vụ món ăn). Ooops, xin lỗi, nó cho thấy rằng tôi đang đi du lịch nước ngoài và đã không có mì ống trong một thời gian, tôi đoán. Nhưng sự tương tự vẫn còn khá tốt! -) và sẽ được khuyên nên từ bỏ achoview và thay vào đó là một ít húng quế tươi [hoặc thậm chí - Tôi là một kẻ dị giáo ...! - bạc hà nhẹ ...] lá - vào giây phút cuối cùng trước khi phục vụ món ăn). Ooops, xin lỗi, nó cho thấy rằng tôi đang đi du lịch nước ngoài và đã không có mì ống trong một thời gian, tôi đoán. Nhưng sự tương tự vẫn còn khá tốt! -)
Vì vậy, trở lại với Python và Ruby, chúng tôi đến với hai ông lớn (về ngôn ngữ phù hợp - rời khỏi thư viện và các công cụ phụ trợ quan trọng khác như công cụ và môi trường, cách nhúng / mở rộng từng ngôn ngữ, v.v. bây giờ - họ sẽ không áp dụng cho tất cả THỰC HIỆN của từng ngôn ngữ, ví dụ: Jython vs Classic Python là hai triển khai của ngôn ngữ Python!):
Trình lặp và bộ mã của Ruby so với trình lặp và trình tạo của Python;
TOTAL của Ruby, "tính năng động" không bị kiểm soát, bao gồm khả năng "mở lại" bất kỳ lớp hiện có nào, bao gồm tất cả các lớp tích hợp sẵn và thay đổi hành vi của nó trong thời gian chạy - so với tính
năng động rộng lớn nhưng bị ràng buộc của Python , không bao giờ thay đổi hành vi của hiện tại các lớp tích hợp và các thể hiện của chúng.
Cá nhân, tôi coi 1 lần rửa (sự khác biệt sâu sắc đến mức tôi có thể dễ dàng thấy mọi người ghét cách tiếp cận và tôn trọng người khác, nhưng trên thang điểm cá nhân của tôi, điểm cộng và điểm trừ thậm chí còn tăng lên); và [2] một vấn đề quan trọng - một vấn đề khiến Ruby phù hợp hơn nhiều cho việc "mày mò", NHƯNG Python phù hợp hơn không kém để sử dụng trong các ứng dụng sản xuất lớn. Theo một cách nào đó, điều đó thật buồn cười, bởi vì cả hai ngôn ngữ đều RẤT năng động hơn hầu hết các ngôn ngữ khác, rằng cuối cùng, sự khác biệt chính giữa chúng từ POV của tôi nên xoay quanh vấn đề đó - rằng Ruby "đi đến mười một" về vấn đề này (tài liệu tham khảo tất nhiên ở đây là "Spinal Tap". Trong Ruby,TÔI CÓ THỂ LÀM ĐIỀU NÀY ! Tức là, tôi có thể tự động thay đổi lớp chuỗi tích hợp để
a = "Xin chào thế giới"
b = "chào thế giới"
nếu a == b
in "bằng! \ n"
khác
in "khác nhau! \ n"
kết thúc
S print in "bằng". Trong python, KHÔNG có cách nào tôi có thể làm điều đó. Với mục đích lập trình siêu dữ liệu, triển khai các khung thử nghiệm và tương tự, khả năng năng động tuyệt vời này của Ruby là vô cùng
hấp dẫn. NHƯNG - nếu chúng ta đang nói về các ứng dụng lớn, được phát triển bởi nhiều người và thậm chí còn được duy trì nhiều hơn, bao gồm tất cả các loại thư viện từ nhiều nguồn khác nhau và cần phải đi vào sản xuất trong các trang web của khách hàng ... tốt, tôi không MUỐN một ngôn ngữ rất QUITE rất năng động, cảm ơn bạn rất nhiều. Tôi ghê tởm ý tưởng về một số thư viện vô tình phá vỡ những cái không liên quan khác dựa vào các chuỗi đó là khác nhau - đó là loại "kênh" ẩn sâu và sâu, giữa các đoạn mã mà TÌM tách ra và NÊN tách ra, nói lên cái chết lập trình quy mô lớn. Bằng cách để bất kỳ mô-đun nào ảnh hưởng đến hành vi của bất kỳ "bí mật" nào khác,
Nếu tôi phải sử dụng Ruby cho một ứng dụng lớn như vậy, tôi sẽ cố gắng dựa vào các hạn chế theo kiểu mã hóa, rất nhiều thử nghiệm (để chạy lại bất cứ khi nào BẤT CỨ thay đổi - ngay cả những gì hoàn toàn không liên quan ...), và tương tự, cấm sử dụng tính năng ngôn ngữ này. Nhưng theo tôi, KHÔNG có tính năng này ngay từ đầu thậm chí còn tốt hơn - giống như bản thân Python sẽ là ngôn ngữ tốt hơn để lập trình ứng dụng nếu một số lượng tích hợp nhất định có thể bị "đóng đinh", vì vậy tôi BIẾT rằng , ví dụ,
len("ciao")
là 4 (thay vì phải lo lắng một cách cao siêu về việc liệu ai đó đã thay đổi ràng buộc tên len
trong __builtins__
mô-đun ...). Tôi hy vọng rằng cuối cùng Python cũng "đóng đinh" các phần mềm dựng sẵn của nó.
Nhưng vấn đề nhỏ, vì việc dựng lại các phần dựng sẵn khá không được chấp nhận cũng như một cách thực hành hiếm gặp trong Python. Trong Ruby, nó gây ấn tượng mạnh với tôi - giống như các
cơ sở vĩ mô quá mạnh của các ngôn ngữ khác (như, nói, Dylan) đưa ra những rủi ro tương tự theo quan điểm của riêng tôi (tôi hy vọng rằng Python không bao giờ có được một hệ thống vĩ mô mạnh như vậy, không vấn đề hấp dẫn là "cho phép mọi người xác định ngôn ngữ nhỏ của riêng họ được nhúng trong chính ngôn ngữ đó" - IMHO, sẽ làm giảm tính hữu dụng tuyệt vời của Python đối với lập trình ứng dụng, bằng cách đưa ra một "phiền toái hấp dẫn" cho người tin học ẩn giấu trong trái tim của mỗi lập trình viên ...).
Alex