Ruby có gì mà Python không có, và ngược lại?


263

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ó ''.startswithphươ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, anotherhoặc bạn có thể chỉ cần import themoduletruy 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__.pytệ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


2
Liên quan đến nhiều kế thừa, chỉ nói "Ruby không" là không rõ ràng. Tôi không thể nghĩ ra bất cứ điều gì bạn có thể làm trong Python với nhiều kế thừa mà bạn không thể làm trong ruby ​​với các mô-đun / "kế thừa mixin". (Thậm chí còn có thể lập luận rằng bao gồm các mô-đun chỉ đơn giản nhiều kế thừa.)
Logan Capaldo

2
Rằng bạn có thể làm điều tương tự theo một cách khác là một đối số không giữ được. Bạn có thể làm mọi thứ ở đây một số cách khác. Và vì các mô-đun không phải là các lớp, nó không phải là nhiều kế thừa. Bạn được hoan nghênh đóng góp các ví dụ mã về cách nó được thực hiện trong Pythons nhiều kế thừa so với các mô-đun Rubys.
Lennart Regebro

3
Mô-đun không phải là Lớp học nhưng Lớp học là Mô-đun. % ruby ​​-e 'p Class <Module' đúng
Logan Capaldo

8
-1 Thật không may, câu hỏi này bỏ lỡ mục tiêu của nó và hầu hết những khác biệt có mục đích không phải là sự khác biệt ở tất cả và rất nhiều thông tin sai lệch!
thiên vị

2
Mô-đun bao gồm trên thực tế là nhiều kế thừa, không chỉ trong khái niệm mà còn được triển khai thực tế trong trình thông dịch Ruby. Khi bao gồm một mô-đun Ruby, nó được đưa vào chuỗi kế thừa giống hệt như các siêu lớp. Phương pháp giải quyết là như nhau. Trong Ruby nhiều mô-đun bao gồm nhiều kế thừa. Bất cứ ai muốn tranh luận điều này là "không giống nhau" về mặt ngữ nghĩa vì nhiều sự thừa kế chỉ là mang tính mô phạm. Điểm của một thứ không phải là "điều tương tự" là gì nếu hiệu ứng giống hệt nhau và dễ dàng đạt được? Một sự khác biệt không có sự khác biệt.
Dave Sims

Câu trả lời:


34

Ruby có các khái niệm về các khối , về cơ bản là đường cú pháp xung quanh một phần của mã; chúng là một cách để tạo các bao đóng và chuyển chúng sang một phương thức khác có thể hoặc không thể sử dụng khối. Một khối có thể được gọi sau này thông qua một yieldtuyên bố.

Ví dụ, một định nghĩa đơn giản về một eachphương thức trên Arraycó thể là một cái gì đó như:

class Array
  def each
    for i in self  
      yield(i)     # If a block has been passed, control will be passed here.
    end  
  end  
end  

Sau đó, bạn có thể gọi điều này như vậy:

# Add five to each element.
[1, 2, 3, 4].each{ |e| puts e + 5 }
> [6, 7, 8, 9]

Python có các hàm ẩn / đóng / lambdas, nhưng nó không hoàn toàn có các khối vì nó thiếu một số đường cú pháp hữu ích. Tuy nhiên, có ít nhất một cách để có được nó theo cách đặc biệt. Xem, ví dụ, ở đây .


6
@Lennart: ngoài ví dụ của bạn chỉ là con ong khủng khiếp thì nó còn sai về mặt cú pháp.

2
@unbeknow: A, đúng rồi. Nhưng nếu đó là một chức năng thay vì một bản in, nó sẽ hoạt động. Trong python 3, nó hoạt động: [print (e + 5) cho e trong [1,2,3,4]] Và khi nói đến sự khủng khiếp, tôi nghĩ rằng mã ruby ​​ở trên là khủng khiếp, vì vậy điều đó rõ ràng chủ quan và do đó không phải là một một phần của câu hỏi này @ John Tôi không nói nó tương đương, tôi đang nói không rõ sự khác biệt so với ví dụ của bạn. @Bastien, không, nhưng bạn có thể làm những điều tương tự không có nghĩa là chúng giống nhau. Sự khác biệt ở đây nên được liệt kê ngay cả khi có những cách otehr để làm điều đó.
Lennart Regebro

22
Tôi là một lập trình viên Python. Tôi muốn xem một ví dụ về cách các khối Ruby giúp bạn viết một cái gì đó chính xác hơn hoặc đẹp hơn so với Python vì nó không có các khối. Ví dụ của bạn có thể được viết: for i in [1, 2, 3, 4]: print (i + 5). Nó không sử dụng các khối, nhưng ngắn gọn và đẹp như ruby ​​mỗi ví dụ.
Manuel Ceron

10
@Manuel, procs rất hữu ích để gắn functor vào các cấu trúc dữ liệu không tầm thường (cây, biểu đồ ...) không thể 'được lặp' và do đó yêu cầu các trình lặp đặc biệt để chuyển ngang. Các khối, là các procs ẩn danh, cho phép bạn triển khai functor trong một biểu thức (so với xác định sau đó thực hiện) giúp tăng tốc đáng kể quá trình mã hóa và làm rõ ý định. Ví dụ: nếu bạn đang tạo cấu trúc dữ liệu biểu đồ, bạn có thể xác định một trình lặp 'mỗi' và sau đó mixin Enumerable sẽ cung cấp cho bạn quyền truy cập vào hàng tá trình lặp (sắp xếp, tất cả?, Bất kỳ?, Grep). Bây giờ bạn gọi một khối ...
thiên vị

4
@RommeDeSerieux, vì nó cần một cái tên trong ngôn ngữ! Hơn nữa, nó là một đối tượng chức năng, không phải là một chức năng. Hãy xem Ruby Docs: "Các đối tượng Proc là các khối mã được liên kết với một tập hợp các biến cục bộ" vì vậy một Proc ẩn danh chỉ là khối và chắc chắn nó không chỉ là một hàm!
thiên vị

28

Ví dụ về Python

Các hàm là các biến hạng nhất trong Python. Bạn có thể khai báo một hàm, truyền nó xung quanh dưới dạng một đối tượng và ghi đè lên nó:

def func(): print "hello"
def another_func(f): f()
another_func(func)

def func2(): print "goodbye"
func = func2

Đây là một tính năng cơ bản của ngôn ngữ kịch bản hiện đại. JavaScript và Lua cũng làm điều này. Ruby không xử lý các chức năng theo cách này; Đặt tên một hàm gọi nó.

Tất nhiên, có nhiều cách để thực hiện những điều này trong Ruby, nhưng chúng không phải là hoạt động hạng nhất. Ví dụ: bạn có thể bọc một hàm với Proc.new để coi nó là một biến - nhưng sau đó nó không còn là hàm nữa; nó là một đối tượng với phương thức "gọi".

Các chức năng của Ruby không phải là các đối tượng hạng nhất

Các chức năng của Ruby không phải là các đối tượng hạng nhất. Các chức năng phải được bọc trong một đối tượng để vượt qua chúng; đối tượng kết quả không thể được coi như một hàm. Các chức năng không thể được chỉ định theo cách thức hạng nhất; thay vào đó, một hàm trong đối tượng chứa của nó phải được gọi để sửa đổi chúng.

def func; p "Hello" end
def another_func(f); method(f)[] end
another_func(:func)      # => "Hello"

def func2; print "Goodbye!"
self.class.send(:define_method, :func, method(:func2))
func                     # => "Goodbye!"

method(:func).owner      # => Object
func                     # => "Goodbye!"
self.func                # => "Goodbye!"    

8
Bạn đang bối rối. Các đối tượng hạng nhất được gán bởi gán : x = y, không phải bằng cách gọi self.class.send(:define_method, :func, method(:func2)). "Ví dụ mẫu" của bạn chỉ ra cách các chức năng của Ruby không phải là hạng nhất. Nếu bạn không đồng ý, hãy đăng câu trả lời của riêng bạn; đừng dính sự nhầm lẫn của bạn trong tôi.
Glenn Maynard

7
Những điều được xác định bởi def ... endtrong ruby ​​không có chức năng. Chúng là các phương thức (cách bạn đã xác định chúng, của Kernel). Các phương thức có thể không bị ràng buộc (sử dụng #methodphương thức), sau đó là các đối tượng. Điều gần nhất mà ruby ​​có với các chức năng là các Procthể hiện, cũng là các đối tượng và có thể được truyền xung quanh hoặc gọi ra. Nó cũng có một cú pháp đặc biệt để chuyển một cuộc gọi lại duy nhất Proccho một phương thức, như John Women'sella thảo luận trong câu trả lời của mình .
hung hăng

4
@Glenn: Tôi hiểu những gì bạn đang nói, nhưng tôi không thể phân biệt được với khẳng định rằng các hàm định nghĩa lại của Ruby - các phương thức là một khái niệm ngữ nghĩa riêng biệt. Nếu bạn muốn chơi trò chơi định nghĩa, hầu hết các mã bắt buộc là các thủ tục, không phải các hàm. Tôi không cố tỏ ra khó khăn, chỉ là tôi tin rằng định nghĩa và tính chính xác là quan trọng. Tôi sẽ đồng ý rằng thao túng một UnboundMethodcó thể là PITA, tho.
hung hăng

5
@Glenn: Vẻ đẹp là trong mắt của kẻ si tình. Tuy nhiên, các phương thức là các đối tượng hạng nhất bằng cách hoàn thành định nghĩa (trong trường hợp này tôi đang đề cập đến định nghĩa Wikipedia). Có lẽ, bạn có một số định nghĩa khác về hạng nhất? Họ có cần Thẻ Flier thường xuyên bạch kim để được nâng cấp lên hạng nhất không?
thiên vị

4
@Glenn Kiểm tra phần Câu hỏi thường gặp của SO "Người khác có thể chỉnh sửa nội dung của tôi?!" - đây là một Wiki cộng đồng.
thiên vị

26

Cuối cùng, tất cả các câu trả lời sẽ chủ quan ở một mức độ nào đó và các câu trả lời được đăng cho đến nay khá nhiều chứng minh rằng bạn không thể chỉ ra bất kỳ tính năng nào không thể thực hiện được bằng ngôn ngữ khác theo cách tương tự (nếu không tương tự) , vì cả hai ngôn ngữ đều rất súc tích và biểu cảm.

Tôi thích cú pháp của Python. Tuy nhiên, bạn phải đào sâu hơn một chút so với cú pháp để tìm ra vẻ đẹp thực sự của Ruby. Có vẻ đẹp giống như sự kiên định của Ruby. Mặc dù không có ví dụ tầm thường nào có thể giải thích hoàn toàn điều này, tôi sẽ cố gắng đưa ra một ví dụ ở đây chỉ để giải thích ý tôi là gì.

Đảo ngược các từ trong chuỗi này:

sentence = "backwards is sentence This"

Khi bạn nghĩ về cách bạn sẽ làm điều đó, bạn sẽ làm như sau:

  1. Chia câu thành lời
  2. Đảo ngược các từ
  3. Nối lại các từ thành một chuỗi

Trong Ruby, bạn sẽ làm điều này:

sentence.split.reverse.join ' '

Chính xác như bạn nghĩ về nó, trong cùng một chuỗi, một phương thức gọi cái khác.

Trong python, nó sẽ trông giống như thế này:

" ".join(reversed(sentence.split()))

Điều đó không khó hiểu, nhưng nó không hoàn toàn có cùng một dòng chảy. Chủ ngữ (câu) được chôn ở giữa. Các hoạt động là một kết hợp của các chức năng và phương thức đối tượng. Đây là một ví dụ tầm thường, nhưng người ta phát hiện ra nhiều ví dụ khác nhau khi thực sự làm việc và hiểu Ruby, đặc biệt là về các nhiệm vụ không tầm thường.


1
Tôi đồng ý. Ruby dường như chảy tự nhiên khi tôi viết nó, vì vậy "zenlike" là một thuật ngữ tốt.
Tin Man

18

Python có tâm lý "chúng ta đều là người lớn ở đây". Do đó, bạn sẽ thấy rằng Ruby có những thứ như hằng số trong khi Python thì không (mặc dù các hằng số của Ruby chỉ đưa ra cảnh báo). Cách suy nghĩ của Python là nếu bạn muốn làm cho một cái gì đó không đổi, bạn nên đặt tên biến trong tất cả các mũ và không thay đổi nó.

Ví dụ: Ruby:

>> PI = 3.14
=> 3.14
>> PI += 1
(irb):2: warning: already initialized constant PI
=> 4.14

Con trăn

>>> PI = 3.14
>>> PI += 1
>>> PI
4.1400000000000006

19
Ha .. điều này chỉ nhắc nhở tôi rằng ít nhất là trong python 2. *, bạn đã có thể thực hiện "Đúng, Sai = Sai, Đúng" ... Tôi tin rằng họ đã sửa chính xác rằng trong python 3.0 ... đó là điều bạn nên làm được ngăn chặn làm.
Tom

11
Cá nhân, tôi thích các hướng dẫn nghiêm ngặt được thi hành bởi ngôn ngữ này vì nó làm cho tất cả các mã được viết bằng ngôn ngữ đó nhất quán. Nó buộc bạn phải tuân theo các nguyên tắc và các nhà phát triển đọc mã của bạn có thể cho biết nhanh những gì. Trong khi hầu hết các lập trình viên Python sử dụng cùng một "phong cách" chung, tôi đã thấy một số mâu thuẫn khá lớn không thể có trong Ruby.
Sasha Chedygov

8
@bias - Tôi không chắc tại sao bạn lại hạ thấp tôi. Câu trả lời này không đồng ý hay không đồng ý với cách làm trăn. Đó chỉ là một tuyên bố thực tế.
Jason Baker

13
@Jason "chúng ta đều là người lớn ở đây" là tuyên bố của một sự thật? Tôi muốn gọi đó là một ý kiến ​​xoay quanh một tính năng, do đó bỏ phiếu xuống.
thiên vị

7
@bias - Nói rằng "chúng ta đều là người lớn ở đây" không có nghĩa là một chút. Đó là một phương châm Python không chính thức, mà tôi tin là được giải thích tốt nhất ở đây: mail.python.org/pipermail/tutor/2003-Oc/10/025932.html
Evan Porter

18

Bạn chỉ có thể nhập các chức năng cụ thể từ một mô-đun trong Python. Trong Ruby, bạn nhập toàn bộ danh sách các phương thức. Bạn có thể "không quan tâm" đến chúng trong Ruby, nhưng đó không phải là tất cả.

BIÊN TẬP:

hãy lấy mô-đun Ruby này:


module Whatever
  def method1
  end

  def method2
  end
end

nếu bạn bao gồm nó trong mã của bạn:


include Whatever

bạn sẽ thấy rằng cả hai method1method2 đã được thêm vào không gian tên của bạn. Bạn không thể chỉ nhập phương thức1 . Bạn có thể nhập cả hai hoặc bạn hoàn toàn không nhập chúng. Trong Python bạn chỉ có thể nhập các phương thức bạn chọn. Nếu cái này có tên thì có lẽ nó được gọi là nhập có chọn lọc?


2
Ô đúng rồi! Python thích không gian tên. Đó không phải là trường hợp của Ruby sao? Bạn không import bla; bla.foo()ở Ruby?
Lennart Regebro

2
Bạn chỉ có thể nhập chức năng a, không phải tất cả các chức năng bên trong. Ví dụ: nếu bạn bao gồm một mô-đun Ruby khai báo 3 hàm không tĩnh, bạn sẽ có tất cả chúng trong không gian tên của mình. Trong python bạn phải viết từ mô-đun nhập *.
Geo

6
Điều đó không dẫn đến nhiều lộn xộn không gian tên?
Lennart Regebro

1
Tôi nghĩ rằng nó làm. Đó là những gì tôi ghét về các mô-đun Ruby.
Geo

8
Ruby không thực sự có một hệ thống mô-đun theo nghĩa tương tự như python. yêu cầu các công việc về cơ bản là bao gồm văn bản với một số kiểm tra để đưa vào hai mặt. Bạn có thể (ab) sử dụng các mô-đun làm không gian tên nhưng modulethực sự là một chút sai lầm. Các mô-đun về cơ bản là các lớp sans new, allocatephương thức. Chúng hoạt động tốt nhất như một cách để chia sẻ mã trên cơ sở từng lớp / đối tượng, không phải là cơ chế để phân vùng thư viện hoặc chia sẻ mã trên các chương trình.
Logan Capaldo

16

Từ trang web của Ruby :

Điểm tương đồng Như với Python, trong Ruby, ...

  • Có một dấu nhắc tương tác (được gọi là irb).
  • Bạn có thể đọc tài liệu trên dòng lệnh (với lệnh ri thay vì pydoc).
  • Không có thiết bị đầu cuối dòng đặc biệt (ngoại trừ dòng mới thông thường).
  • Chuỗi ký tự có thể trải rộng trên nhiều dòng như chuỗi ba trích dẫn của Python.
  • Chân đế là dành cho danh sách, và niềng răng là dành cho dicts (trong Ruby, được gọi là băm băm).
  • Mảng hoạt động như nhau (thêm chúng tạo thành một mảng dài, nhưng việc soạn chúng như thế này a3 = [ a1, a2 ]sẽ cung cấp cho bạn một mảng các mảng).
  • Các đối tượng được gõ mạnh mẽ và năng động.
  • Mọi thứ đều là một đối tượng và các biến chỉ là tham chiếu đến các đối tượng.
  • Mặc dù các từ khóa là một chút khác nhau, ngoại lệ hoạt động như nhau.
  • Bạn đã có các công cụ doc nhúng (Ruby's được gọi là ndoc).

Sự khác biệt Không giống như Python, trong Ruby, ...

  • Chuỗi là đột biến.
  • Bạn có thể tạo các hằng số (các biến có giá trị mà bạn không có ý định thay đổi).
  • Có một số quy ước trường hợp được thi hành (ví dụ tên lớp bắt đầu bằng chữ in hoa, các biến bắt đầu bằng chữ thường).
  • Chỉ có một loại bộ chứa danh sách (một mảng) và nó có thể thay đổi.
  • Các chuỗi được trích dẫn kép cho phép các chuỗi thoát (như \ t) và cú pháp thay thế biểu thức đặc biệt của biểu thức (cho phép bạn chèn trực tiếp kết quả của các biểu thức Ruby vào các chuỗi khác mà không phải "thêm" + "chuỗi" + "với nhau") . Các chuỗi trích dẫn đơn giống như "chuỗi thô" của Python.
  • Không có các lớp phong cách mới của Wikipedia và các lớp phong cách cũ của phong cách cũ. Chỉ cần một loại.
  • Bạn không bao giờ truy cập trực tiếp các thuộc tính. Với Ruby, đó là tất cả các cuộc gọi phương thức.
  • Dấu ngoặc cho các cuộc gọi phương thức thường là tùy chọn.
  • Có công khai, riêng tư và được bảo vệ để thực thi quyền truy cập, thay vì Python _voluntary_ underscore __convention__.
  • Mùi hỗn hợp của người dùng được sử dụng thay vì thừa kế nhiều lần.
  • Bạn có thể thêm hoặc sửa đổi các phương thức của các lớp dựng sẵn. Cả hai ngôn ngữ đều cho phép bạn mở và sửa đổi các lớp tại bất kỳ thời điểm nào, nhưng Python ngăn chặn sửa đổi các phần dựng sẵn - Ruby thì không.
  • Bạn đã đúng và sai thay vì Đúng và Sai (và không thay vì Không).
  • Khi được kiểm tra cho sự thật, chỉ có sai và không đánh giá đến một giá trị sai. Mọi thứ khác đều đúng (bao gồm 0, 0,0, "" và []).
  • Đó là elsif thay vì elif.
  • Đó là yêu cầu thay vì nhập khẩu. Mặt khác, cách sử dụng là như nhau.
  • Các nhận xét kiểu thông thường về (các) dòng trên các thứ (thay vì các tài liệu bên dưới chúng) được sử dụng để tạo tài liệu.
  • Có một số phím tắt, mặc dù cung cấp cho bạn nhiều thứ để nhớ hơn, bạn nhanh chóng tìm hiểu. Họ có xu hướng làm cho Ruby vui vẻ và rất năng suất.

2
"Đó là yêu cầu thay vì nhập khẩu. Mặc dù vậy, cách sử dụng là như nhau." Có vẻ là hoàn toàn không chính xác.
Glenjamin

Ngoài ra còn có Bộ trong Ruby mà mọi người hiếm khi sử dụng, nhưng chúng được tích hợp sẵn. Vì vậy, tôi có thể nói, Stuff_in_backpack = Set.new; Stuff_in_backpack << "máy tính"; Stuff_in_backpack << "giày"; # và tập hợp sẽ giữ tất cả các giá trị mà không đảm bảo thứ tự.
zachaysan

12

Những gì Ruby có trên Python là khả năng ngôn ngữ kịch bản của nó. Ngôn ngữ kịch bản trong ngữ cảnh này có nghĩa là được sử dụng cho "mã keo" trong tập lệnh shell và thao tác văn bản chung.

Chúng hầu hết được chia sẻ với Perl. Các biểu thức chính quy tích hợp hạng nhất, $ -Variabled, các tùy chọn dòng lệnh hữu ích như Perl (-a, -e), v.v.

Cùng với cú pháp ngắn gọn nhưng tuyệt vời của nó, nó hoàn hảo cho các loại nhiệm vụ này.

Python đối với tôi là một ngôn ngữ kinh doanh được đánh máy linh hoạt, rất dễ học và có một cú pháp gọn gàng. Không "ngầu" như Ruby nhưng gọn gàng. Những gì Python có trên Ruby đối với tôi là số lượng lớn các ràng buộc cho các lib khác. Liên kết với Qt và các lib GUI khác, nhiều thư viện hỗ trợ trò chơi và và. Ruby có ít hơn nhiều. Mặc dù các ràng buộc được sử dụng nhiều, ví dụ như Cơ sở dữ liệu có chất lượng tốt, tôi thấy các lib thích hợp được hỗ trợ tốt hơn trong Python ngay cả khi trong cùng một thư viện cũng có ràng buộc Ruby.

Vì vậy, tôi muốn nói cả hai ngôn ngữ đều có cách sử dụng và đó là nhiệm vụ xác định ngôn ngữ nào sẽ sử dụng. Cả hai đều đủ dễ để học. Tôi sử dụng chúng cạnh nhau. Ruby cho kịch bản và Python cho các ứng dụng độc lập.


1
Câu hỏi từ một người chưa biết Ruby: "$ -Variabled" nghĩa là gì? Bạn có nghĩa là các biến toàn cầu? Nếu vậy, trong Python, một biến được định nghĩa trong một mô-đun bên ngoài một lớp hoặc hàm là toàn cục. Nếu không - sự khác biệt là gì?
Anon

1
Anon: nếu bạn khai báo một biến $ ở bất cứ đâu trong mã thì nó là toàn cục vì tiền tố. Do đó, không quan trọng nó được định nghĩa ở đâu, nó luôn luôn là toàn cầu và luôn được biết đến như vậy.
Robert K

8
Không chính xác, thực ra tôi có nghĩa là các biến được xác định trước như $ _, $ 1, v.v ... Đây là những biến được tự động điền với các giá trị bằng chính ruby. $ _ là dòng cuối cùng được đọc. $ 1, $ 2, v.v. là các biểu thức khớp thường xuyên từ trận đấu cuối cùng. Xem ở đây để biết danh sách đầy đủ: zenspider.com/Lacular/Ruby/QuickRef.html#17 Về cơ bản, đây là một bản hack cho các tập lệnh nhỏ gọn. Bạn cũng có thể nhận được tất cả thông tin qua các lệnh gọi API, nhưng sử dụng biến $ thì ngắn gọn hơn. Những loại biến như vậy không phù hợp với phong cách của Python, họ cố tình bỏ chúng đi.
haffax

Cảm ơn vì liên kết zenspider - đã tìm kiếm một cái gì đó giống như vậy để có cảm giác nhanh chóng (không hướng dẫn) cho Ruby.
Anon

12

Tôi không nghĩ "Ruby có X và Python thì không, trong khi Python có Y và Ruby thì không" là cách hữu ích nhất để xem xét nó. Chúng là những ngôn ngữ khá giống nhau, với nhiều khả năng được chia sẻ.

Ở một mức độ lớn, sự khác biệt là những gì ngôn ngữ làm cho thanh lịch và dễ đọc. Để sử dụng một ví dụ bạn đã đưa ra, cả hai về mặt lý thuyết đều có lambdas, nhưng các lập trình viên Python có xu hướng tránh chúng và các cấu trúc được tạo bằng cách sử dụng chúng không nhìn ở bất cứ đâu gần như dễ đọc hoặc thành ngữ như trong Ruby. Vì vậy, trong Python, một lập trình viên giỏi sẽ muốn có một lộ trình khác để giải quyết vấn đề so với trong Ruby, chỉ vì đó thực sự cách tốt hơn để làm điều đó.


5
Tôi đồng ý rằng lambdas có phạm vi hạn chế và không hữu ích trong nhiều trường hợp. Tuy nhiên, tôi không nghĩ thật công bằng khi nói rằng các lập trình viên Python tránh họ như bệnh dịch.
Jason Baker

1
Tôi đồng ý rằng lambdas được sử dụng thường xuyên với Python - như với bản đồ, bộ lọc, thu nhỏ. Sự khác biệt lớn dường như là lambdas Python bị giới hạn trong các biểu thức trong khi các khối Ruby có thể là đa dòng và liên quan đến các câu lệnh. Ấn tượng chung của tôi từ những gì tôi đã đọc về Ruby là tính năng này nói riêng làm cho Rubyist đi theo cách tiếp cận DSL, trong khi Pythonistas có nhiều khả năng sẽ tạo API. Thông tin của tôi về Ruby vẫn rất hời hợt.
Anon

2
@Lennart: Các khối đa dòng được sử dụng mọi lúc trong Ruby - thực sự thường xuyên hơn tôi thấy lambdas được sử dụng trong mã Python thành ngữ. Để biết ví dụ phổ biến, hãy xem info.michael-simons.eu/2007/08/06/rails-respond_to-method .
Chuck

1
@Lennart: Không, nó không sử dụng năng suất. (Dù sao thì năng suất của Ruby hoàn toàn khác với Python - nó không trả về trình tạo.) Nó sẽ không có ý nghĩa khi viết for format in respond_to(). Các respond_tophương pháp không trả lại bất cứ điều gì có ý nghĩa - nó chỉ đơn giản là đáp ứng các yêu cầu HTTP hiện tại. Các dotrong respond_to dolà sự khởi đầu của một khối. Trong khối đó, chúng tôi nói chuyện với một đối tượng tạm thời (được gắn nhãn formattrong ví dụ này) thực hiện DSL rất cơ bản để đáp ứng yêu cầu HTTP.
Chuck

3
Bạn có thể 'mixin Enumerable' chống lại một trình tạo và ngay lập tức nhận được 30 trình lặp mới và tuyệt vời không? Bạn cần xem xét toàn bộ ngôn ngữ trước khi bạn hiểu tại sao các khối / Procs lại tuyệt vời.
thiên vị

12

Tôi muốn đề xuất một biến thể của câu hỏi ban đầu, "Ruby có gì mà Python không có, và ngược lại?" thừa nhận câu trả lời đáng thất vọng, "Chà, bạn có thể làm gì với Ruby hoặc Python mà không thể thực hiện được trong Intercal?" Không có gì ở cấp độ đó, bởi vì Python và Ruby đều là một phần của gia đình hoàng gia rộng lớn đang ngồi trên ngai vàng của Turing.

Nhưng những gì về điều này:

Những gì có thể được thực hiện một cách duyên dáng và tốt đẹp trong Python mà không thể được thực hiện trong Ruby với vẻ đẹp và kỹ thuật tốt như vậy, hoặc ngược lại?

Điều đó có thể thú vị hơn nhiều so với so sánh tính năng đơn thuần.


một nhận xét tốt nhất. vẫn là +1 của tôi
nawfal

11

Python có một cú pháp dựng sẵn rõ ràng để hiểu danh sách và trình tạo trong khi trong Ruby bạn sẽ sử dụng các khối bản đồ và mã.

Đối chiếu

list = [ x*x for x in range(1, 10) ]

đến

res = (1..10).map{ |x| x*x }

Làm thế nào để hiểu danh sách không phải là một Python đơn giản ? và có một chức năng bản đồ trong Python.
SilentGhost

Nhưng không có cú pháp hiểu danh sách trong Ruby
Dario

Python: res = map (lambda x: x * x, phạm vi (1,10))
GogaRieger

Python:res=map(2 .__rpow__, range(1,10))
John La Rooy

11

"Các biến bắt đầu bằng chữ in hoa trở thành hằng số và không thể sửa đổi"

Sai lầm. Họ có thể.

Bạn chỉ nhận được một cảnh báo nếu bạn làm.


2
Nếu một ngôn ngữ đưa ra cảnh báo cho bạn về một hoạt động, thì theo ý kiến ​​của tôi, bạn rất có thể coi hoạt động đó là "không thể". Bất cứ điều gì khác là điên rồ.
porgarmingduod

11

Một số chi tiết về phía cơ sở hạ tầng:

  • Python có khả năng tích hợp tốt hơn nhiều với C ++ (thông qua những thứ như Boost.Python , SIPPy ++ ) so với Ruby, trong đó các tùy chọn dường như được viết trực tiếp dựa trên API trình thông dịch Ruby (dĩ nhiên bạn cũng có thể làm với Python nhưng trong cả hai trường hợp, làm như vậy là mức độ thấp, tẻ nhạt và dễ bị lỗi) hoặc sử dụng SWIG (trong khi nó hoạt động và chắc chắn là tuyệt vời nếu bạn muốn hỗ trợ nhiều ngôn ngữ, không tốt như Boost.Python hoặc SIP nếu bạn đang đặc biệt tìm cách ràng buộc C ++).

  • Python có một số môi trường ứng dụng web (Django, Pylons / Turbogears, web.py, có thể ít nhất là một nửa tá khác), trong khi Ruby (có hiệu quả) có một: Rails. (Các khung web Ruby khác tồn tại, nhưng dường như có một thời gian khó khăn để có nhiều lực kéo chống lại Rails). Là khía cạnh này tốt hay xấu? Khó nói, và có lẽ khá chủ quan; Tôi có thể dễ dàng tưởng tượng ra các lập luận rằng tình huống Python tốt hơn và tình huống Ruby tốt hơn.

  • Về mặt văn hóa, cộng đồng Python và Ruby có vẻ hơi khác nhau, nhưng tôi chỉ có thể gợi ý về điều này vì tôi không có nhiều kinh nghiệm tương tác với cộng đồng Ruby. Tôi thêm điều này chủ yếu với hy vọng rằng ai đó có nhiều kinh nghiệm với cả hai có thể khuếch đại (hoặc từ chối) tuyên bố này.


7
Điểm thứ hai của bạn là tốt nhất thông tin sai. Bạn nên bắt đầu bằng cách nhìn vào Rack và Sinatra
Max Ogden

6
Tôi lưu ý rõ ràng rằng các ngăn xếp Rails khác tồn tại; Tôi chỉ không nghĩ rằng bất cứ ai đang thực sự sử dụng chúng. Kiểm tra Sinatra và Rack không thay đổi chính xác ấn tượng đó. Bạn có thực sự nghĩ rằng, Sinatra (tổng cộng 94 câu hỏi SO), hoặc Cắm trại (tổng cộng 2 câu hỏi SO), hoặc bất kỳ câu hỏi nào khác, thực sự có một cộng đồng người dùng / cộng đồng thực sự không? Hầu hết trong số họ thậm chí không có người dùng thực tế, theo như tôi có thể nói. So sánh với Django (4K +) hoặc Rails (7K +) hoặc thậm chí là web.py cho vấn đề đó.
Jack Lloyd

1
Sinatra thực sự khá phổ biến cho các nhiệm vụ nhẹ, khác nhau do DSL của nó. Nó chỉ ít được sử dụng vì MVC của Rail cung cấp nhiều hơn. Rails thực sự được xây dựng trên Rack - Đó là những gì làm cho Phusion Pasbah có thể.
thay thế

11

Sao chép / dán không biết xấu hổ từ: Alex Martelli trả lời về chủ đề " Điều gì tốt hơn về Ruby so với Python " từ danh sách gửi thư comp.lang.python .

Ngày 18 tháng 8 năm 2003, 10:50 sáng 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 về nó hơn là đưa chúng 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 đến đá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 cảm thấy mệt mỏi, trong Ruby, khi gõ "kết thúc" ngớ ngẩn ở cuối mỗi khối (thay vì chỉ vô ý) - nhưng sau đó tôi phải tránh gõ từ 'ngớ ngẩn không kém': 'mà Python yêu cầu 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 chỉ 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ố lượng tranh luận về một vấn đề tỷ lệ nghịch với vấn đề tầm quan trọng thực tế).

Chỉnh sửa (bởi AM 6/19/2010 11:45): đây còn được gọi là "vẽ tranh đạp xe" (hay nói ngắn gọn là "đạp xe") - một lần nữa, tham chiếu đến Northcote Parkinson, người đã đưa ra "các cuộc tranh luận màu gì để vẽ chiếc xe đạp "như một ví dụ điển hình của" những cuộc tranh luận sôi nổi về những chủ đề tầm thường ". (cuối bản chỉnh sửa).

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ỉ để lại đề cập đến bất kỳđối tượng, không có toán tử tham gia, vì có nghĩa 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ó "cách gọi ngầm" tương tự, như Visual Basic) - nhưng 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 mà tôi có thể ' Để có được một tham chiếu đến đối tượng bằng cách chỉ đề cập đến nó, tôi sẽ cần phải 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ó!" Các 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ọ :-). của các hàm (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 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ọ :-). của các hàm (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 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 được (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, tấ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 đó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 rõ ràng đó là cái 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, thay vì 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, thà 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 achovies và thay vào đó là một ít rau 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! -) - 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! -) - 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 ta đế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!):

  1. 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;

  2. 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 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 sao cho a = "Hello World" b = "hello world" nếu a == b in "bằng! \ N" khác in "khác! \ N" end SILL in " công bằng". Trong python, KHÔNG có cách nào tôi có thể làm điều đó. Với mục đích siêu lập trình, thực hiện 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ỳ "tình cờ" nào khác, khả năng biến đổi ngữ nghĩa của các loại tích hợp chỉ là ý tưởng BAD cho lập trình ứng dụng sản xuất,

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 bài kiểm tra (để 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ụ như, lEN ( "ciao") là 4 (thay vì phải lo lắng về việc liệu giác của ai đó thay đổi các ràng buộc của 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 dựng sẵn của nó.

Nhưng vấn đề nhỏ là, 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 đề lôi cuố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


9

Một số người khác từ:

http://www.ruby-lang.org/en/documentation/ruby-from-other-lacular/to-ruby-from-python/

(Nếu tôi đã trình bày sai bất cứ điều gì hoặc bất kỳ điều nào trong số này đã thay đổi về phía Ruby kể từ khi trang đó được cập nhật, ai đó sẽ thoải mái chỉnh sửa ...)

Các chuỗi có thể thay đổi trong Ruby, không phải trong Python (nơi các chuỗi mới được tạo bởi "thay đổi").

Ruby có một số quy ước trường hợp được thi hành, Python thì không.

Python có cả danh sách và bộ dữ liệu (danh sách bất biến). Ruby có các mảng tương ứng với danh sách Python, nhưng không có biến thể bất biến nào trong số chúng.

Trong Python, bạn có thể truy cập trực tiếp các thuộc tính đối tượng. Trong Ruby, nó luôn thông qua các phương thức.

Trong Ruby, dấu ngoặc đơn cho các cuộc gọi phương thức thường là tùy chọn, nhưng không phải bằng Python.

Ruby có công khai, riêng tư và được bảo vệ để thực thi quyền truy cập, thay vì quy ước sử dụng dấu gạch dưới và đặt tên của Python.

Python có nhiều sự kế thừa. Ruby có "mixins."

Và một liên kết rất phù hợp khác:

http://c2.com/cgi/wiki?PythonVsRuby

Đặc biệt, liên kết đến một cái tốt khác của Alex Martelli , người cũng đã đăng rất nhiều thứ tuyệt vời ở đây trên SO:

http://groups.google.com/group/comp.lang.python/msg/028422d707512283


1
Trong ruby, bạn có thể chỉ cần đóng băng mảng của mình để thay đổi nó thành một thứ không thay đổi
user163365

Bài đăng tuyệt vời của Alex Martelli :)
Skilldrick

8

Tôi không chắc về điều này, vì vậy tôi thêm nó vào làm câu trả lời trước.

Python coi các phương thức không liên kết là các hàm

Điều đó có nghĩa là bạn có thể gọi một phương thức như theobject.themethod()hoặc bằng TheClass.themethod(anobject).

Chỉnh sửa: Mặc dù sự khác biệt giữa các phương thức và hàm là nhỏ trong Python và không tồn tại trong Python 3, nhưng nó cũng không tồn tại trong Ruby, đơn giản vì Ruby không có chức năng. Khi bạn xác định các hàm, bạn thực sự đang xác định các phương thức trên Object.

Nhưng bạn vẫn không thể sử dụng phương thức của một lớp và gọi nó là một hàm, bạn sẽ phải buộc nó vào đối tượng bạn muốn gọi, điều này gây khó khăn hơn nhiều.


Ruby hoàn toàn không có chức năng. Điều đó nói rằng, TheClass.instance_method(:themethod).bind(anobject).callsẽ là viên ruby ​​tương đương.
Logan Capaldo

Oh. Vì vậy, có một số loại chính ma thuật khi bạn xác định một chức năng không phải trên một lớp rõ ràng?
Lennart Regebro

Có, các phương thức được xác định ở cấp cao nhất là các phương thức riêng tư của Object.
Logan Capaldo

1
FWIW, dường như trong Python, các hàm và phương thức thực sự là cùng một loại và hành vi khác nhau của chúng đến từ các mô tả: users.rcn.com/python/doad/ .
Bastien Léonard

1
Nhưng nếu bạn liên kết nó với một đối tượng, thì nó không bị ràng buộc. Tât nhiên. :-) Và chúng cũng giống như vậy trong Python. Chỉ là Ruby không thực sự có chức năng. Và điều đó có nghĩa là tuyên bố của tôi là chính xác. Bạn có thể gọi một phương thức không liên kết như thể đó là một hàm trong Python. Và điều đó thực sự hữu ích, điều đó có nghĩa là bạn có thể gọi một phương thức được định nghĩa trên một lớp trên một đối tượng không có lớp đó, đôi khi rất hữu ích.
Lennart Regebro

7

Tôi muốn đề cập đến API mô tả Python cho phép một người tùy chỉnh "giao tiếp" từ đối tượng đến thuộc tính. Một điều đáng chú ý là, trong Python, người ta có thể tự do thực hiện một giao thức thay thế thông qua việc ghi đè mặc định được đưa ra thông qua việc thực hiện mặc định của __getattribute__phương thức. Hãy để tôi cung cấp thêm chi tiết về những điều đã nói ở trên. Mô tả là các lớp thông thường với __get__, __set__và / hoặc __delete__phương thức. Khi thông dịch viên gặp phải một cái gì đó như anObj.anAttr, sau đây được thực hiện:

  • __getattribute__phương thức anObjđược gọi
  • __getattribute__ lấy ra một đối tượng anAttr từ lớp dict
  • nó kiểm tra xem đối tượng có abAttr __get__, __set__hoặc __delete__đối tượng callable
  • bối cảnh (nghĩa là đối tượng người gọi hoặc lớp và giá trị, thay vì đối tượng sau, nếu chúng ta có setter) được truyền cho đối tượng có thể gọi được
  • kết quả được trả về.

Như đã đề cập, đây là hành vi mặc định. Một là miễn phí để thay đổi giao thức bằng cách thực hiện lại __getattribute__.

Kỹ thuật này mạnh hơn nhiều so với trang trí.


6

Ruby đã hỗ trợ tiếp tục dựng sẵn bằng cách sử dụng callcc.

Do đó, bạn có thể thực hiện những thứ hay ho như toán tử amb


Tôi ước tôi hiểu callcc. Bạn có thể đưa ra một kịch bản ứng dụng trần tục hơn Nhà điều hành mơ hồ của McCarthy, để đánh giá cao các merrits của nó không? Ý tôi là một cái gì đó trong thế giới thực, không phải thứ CS thú vị?!
ThomasH

"Công cụ CS sôi nổi" là có thật. Dành chút thời gian để tìm hiểu: intertwingly.net/blog/2005/04/13/Continuations-for-Curmudgeons
Stephen Eilert


5

Python có tài liệu và ruby ​​không ... Hoặc nếu không, chúng không thể truy cập dễ dàng như trong python.

Thi thiên Nếu tôi sai, xin vui lòng, để lại một ví dụ? Tôi có một cách giải quyết rằng tôi có thể tham gia vào các lớp khá dễ dàng nhưng tôi muốn có một loại tính năng theo kiểu "đặc trưng".


3
không có chuỗi, nhưng có RDoc. Vì vậy, có, không dễ dàng truy cập, nhưng không bị ẩn 100%.
Omar Qureshi

Ruby không sử dụng tài liệu. Nó làm tài liệu theo một cách khác.
Chuck

1
Omar: vâng, tôi biết về ndoc nhưng afaik, chúng không "dễ tiếp cận" như các tài liệu của python. Ví dụ, nếu tôi có một lớp và tôi muốn xuất tài liệu thứ tự từ trong lớp thì công việc khá lớn của nó. Những gì tôi đã làm là tôi tạo tài liệu ri mà tôi cố gắng cập nhật2date và sau đó lấy thông tin đó vi ri. Chắn không đến mức giống như docstrings python của ..
rasjani

Tài liệu có thể được sử dụng để cung cấp doctests. Có cái gì đó như thế cho Ruby?
Regennro Lennart

2
Vâng, nó được gọi là "Ruby Doctest". Đối với các tài liệu có liên quan, tất cả những gì thực sự quan trọng là bạn có tài liệu có thể đọc được ở đâu đó bao gồm các đoạn mã có thể kiểm tra - nó không tạo ra sự khác biệt cho dù đó là trong một chuỗi tài liệu hay trong một nhận xét.
Chuck

5

Ruby có một vòng lặp theo dòng trên các tệp đầu vào (cờ '-n') từ dòng lệnh để nó có thể được sử dụng như AWK. Ruby one-liner này:

ruby -ne 'END {puts $.}'

sẽ đếm các dòng như AWK one-liner:

awk 'END{print NR}'

Ruby có tính năng này thông qua Perl, lấy nó từ AWK như một cách để đưa các sysadins lên tàu với Perl mà không phải thay đổi cách họ làm việc.


1
Tôi muốn thêm rằng hỗ trợ dòng lệnh của Python khá yếu. Bên cạnh vòng lặp tự động bị thiếu, bạn không thể đặt một vài câu lệnh trong một dòng đơn và chuyển nó dưới dạng đối số dòng lệnh một chuỗi cho trình thông dịch. Ít nhất tôi đã không làm như vậy.
ThomasH

Tất nhiên bạn có thể. Nhưng bạn sẽ (như với bất kỳ ngôn ngữ otehr nào) cần kèm theo là trong ngoặc kép.
Lennart Regebro

Python không được sử dụng trên dòng lệnh, vì bạn phải rõ ràng về một số thứ (như sys.stdin) nếu bạn muốn sử dụng nó theo cách đópython -c "import sys; print len(list(sys.stdin))"
u0b34a0f6ae

5

Ruby có sigils và twigils, Python thì không.

Biên tập : Và một điều rất quan trọng mà tôi đã quên (sau tất cả, trước đó chỉ là để bùng cháy một chút :-p):

Python có trình biên dịch JIT ( Psyco ), ngôn ngữ cấp thấp hơn để viết mã nhanh hơn ( Pyrex ) và khả năng thêm mã C ++ nội tuyến ( Dệt ).


Đúng, nhưng đó chỉ là cú pháp.
Lennart Regebro

6
Chà, nếu bạn muốn đi theo con đường đó: cả hai đều hoàn thành Turing. Mọi thứ khác chỉ là cú pháp.
Jörg W Mittag

Có và một sự khác biệt cú pháp nhập khẩu ;-)
fortran

1
Nó quan trọng như thế nào nếu bạn viết @foo hoặc self.foo?
Lennart Regebro

1
@ Jörg: OK, gọi nó là "cú pháp" khác. Vấn đề là @foo và self.foo làm điều tương tự, đó thực sự không phải là chức năng mà Ruby có và Python thì không.
Lennart Regebro

5

Con trăn của tôi bị rỉ sét, vì vậy một số trong số này có thể là con trăn và tôi chỉ không nhớ / không bao giờ học ở nơi đầu tiên, nhưng đây là vài con đầu tiên tôi nghĩ đến:

Khoảng trắng

Ruby xử lý khoảng trắng hoàn toàn khác nhau. Đối với người mới bắt đầu, bạn không cần thụt lề bất cứ điều gì (có nghĩa là không thành vấn đề nếu bạn sử dụng 4 dấu cách hoặc 1 tab). Nó cũng thực hiện tiếp tục dòng thông minh, do đó, sau đây là hợp lệ:

def foo(bar,
        cow)

Về cơ bản, nếu bạn kết thúc với một toán tử, nó chỉ ra điều gì đang xảy ra.

Hỗn hợp

Ruby có các mixin có thể mở rộng các thể hiện thay vì các lớp đầy đủ:

module Humor
  def tickle
    "hee, hee!"
  end
end
a = "Grouchy"
a.extend Humor
a.tickle    »   "hee, hee!"

Enums

Tôi không chắc đây có phải là máy phát điện không, nhưng với Ruby 1.9 ruby ​​như enum, vì vậy

>> enum = (1..4).to_enum
=> #<Enumerator:0x1344a8>

Tham khảo: http://blog.nuclearsquid.com/writings/ruby-1-9-what-s-new-what-s-changed

"Đối số từ khóa"

Cả hai mục được liệt kê đều được hỗ trợ trong Ruby, mặc dù bạn không thể bỏ qua các giá trị mặc định như thế. Bạn có thể đi theo thứ tự

def foo(a, b=2, c=3)
  puts "#{a}, #{b}, #{c}"
end
foo(1,3)   >> 1, 3, 3
foo(1,c=5) >> 1, 5, 3
c          >> 5

Lưu ý rằng c = 5 thực sự gán biến c trong phạm vi gọi giá trị 5 và đặt tham số b là giá trị 5.

hoặc bạn có thể làm điều đó với băm, giải quyết vấn đề thứ hai

def foo(a, others)
  others[:b] = 2 unless others.include?(:b)
  others[:c] = 3 unless others.include?(:c)
  puts "#{a}, #{others[:b]}, #{others[:c]}"
end
foo(1,:b=>3) >> 1, 3, 3
foo(1,:c=>5) >> 1, 2, 5

Tham khảo: Hướng dẫn của Ruby Progammer về Ruby


Ví dụ thứ hai của bạn foo (1, c = 5) không làm những gì bạn nghĩ nó làm. Ruby không có tham số được đặt tên.
Horseyguy

5
Python có tiếp tục dòng ẩn bên trong dấu ngoặc (, [hoặc{
u0b34a0f6ae

5

Bạn có thể có mã trong định nghĩa lớp trong cả Ruby và Python. Tuy nhiên, trong Ruby bạn có một tham chiếu đến lớp (tự). Trong Python bạn không có tham chiếu đến lớp, vì lớp này chưa được xác định.

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ừ cơ thể định nghĩa lớp trong Python.


Bạn có thể cung cấp thêm chi tiết (như mã) cho điểm đầu tiên của bạn?
Loïc Wolff

Mã ví dụ là một ý tưởng tốt, tôi đã thêm rằng, mặc dù trường hợp này là tầm thường.
Lennart Regebro

@SilentGhost: Tôi không thể nghĩ ra cái nào không thực sự tối nghĩa ngay bây giờ. :)
Lennart Regebro

bạn có thể truy cập vào tên lớp bên trong lớp trong python: class foo (): def init __ (tự): in tự .__ lớp .__ name__
txwikinger

1
@txwikinger: vâng, nhưng không phải trong cơ thể của lớp, được thực thi cùng lúc với classcâu lệnh.
Bastien Léonard

4

Cú pháp không phải là một điều nhỏ, nó có tác động trực tiếp đến cách chúng ta suy nghĩ. Nó cũng có ảnh hưởng trực tiếp đến các quy tắc chúng tôi tạo cho các hệ thống chúng tôi sử dụng. Ví dụ, chúng ta có thứ tự các phép toán do cách chúng ta viết các phương trình toán học hoặc câu. Ký hiệu chuẩn cho toán học cho phép mọi người đọc nó nhiều hơn một cách và đi đến các câu trả lời khác nhau cho cùng một phương trình. Nếu chúng ta đã sử dụng ký hiệu tiền tố hoặc hậu tố, chúng ta sẽ tạo ra các quy tắc để phân biệt các số cần thao tác thay vì chỉ có các quy tắc cho thứ tự tính toán các giá trị.

Ký hiệu chuẩn làm cho nó rõ ràng những con số mà chúng ta đang nói đến trong khi đưa ra thứ tự để tính toán chúng mơ hồ. Ký hiệu tiền tố và hậu tố tạo ra thứ tự tính toán đơn giản trong khi làm cho các số không rõ ràng. Python sẽ có lambdas đa dòng nếu không phải do những khó khăn gây ra bởi khoảng trắng cú pháp. (Các đề xuất tồn tại để loại bỏ loại điều này mà không nhất thiết phải thêm các dấu phân cách khối rõ ràng.)

Tôi thấy việc viết điều kiện dễ dàng hơn khi tôi muốn điều gì đó xảy ra nếu một điều kiện sai dễ viết hơn với câu lệnh trừ khi trong Ruby so với cách xây dựng "if-not" tương đương về mặt ngữ nghĩa trong Ruby hoặc các ngôn ngữ khác. Nếu hầu hết các ngôn ngữ mà mọi người đang sử dụng ngày nay đều có sức mạnh như nhau, làm thế nào cú pháp của mỗi ngôn ngữ có thể được coi là một điều tầm thường? Sau các tính năng cụ thể như khối và cơ chế kế thừa, vv cú pháp là phần quan trọng nhất của ngôn ngữ, hầu như không phải là một điều hời hợt.

Bề ngoài là những phẩm chất thẩm mỹ của cái đẹp mà chúng ta gán cho cú pháp. Thẩm mỹ không liên quan gì đến cách nhận thức của chúng ta hoạt động, cú pháp làm.


"Bình luận" này dài gấp ba lần những gì được cho phép trong một bình luận, bất kể đại diện.
Andrew Grimm

Điều này thực sự có vẻ tốt như là một câu trả lời cho tôi. Chỉnh sửa bit "đây là một bình luận".
Bill the Lizard

3

Ngạc nhiên khi thấy không có gì đề cập đến cơ chế "thiếu phương pháp" của ruby. Tôi sẽ đưa ra ví dụ về các phương thức find_by _... trong Rails, như một ví dụ về sức mạnh của tính năng ngôn ngữ đó. Tôi đoán là một cái gì đó tương tự có thể được thực hiện trong Python, nhưng theo hiểu biết của tôi thì nó không tồn tại.


Python có get_attribution , về cơ bản hoàn thành điều tương tự như phương thức_missing của Ruby.
mipadi

3
Tại sao các nhà phát triển python luôn bị đau mông khi ruby ​​được đề cập MỌI NƠI? Bạn không thể phủ nhận điều này không đúng.
aarona

method_missingcó thể được mô phỏng bằng Python trong một số trường hợp : class M(): def __getattr__(self, n): return lambda: "Missing! " + n; M().hi(). Tuy nhiên, có một số khác biệt nhỏ và tôi nghi ngờ đó là thành ngữ trong Python :-)

1
@DJTripleThreat: Tôi phủ nhận rằng đó là sự thật.
Lennart Regebro

3

Một sự khác biệt khác về lambdas giữa Python và Ruby được thể hiện qua vấn đề Accumulator Generator của Paul Graham . In lại tại đây:

Viết hàm foo lấy số n và trả về hàm lấy số i và trả về n tăng theo i. Lưu ý: (a) số đó, không phải số nguyên, (b) tăng theo, không cộng.

Trong Ruby, bạn có thể làm điều này:

def foo(n)
  lambda {|i| n += i }
end

Trong Python, bạn sẽ tạo một đối tượng để giữ trạng thái n:

class foo(object):
    def __init__(self, n):
        self.n = n
    def __call__(self, i):
        self.n += i
        return self.n

Một số người có thể thích cách tiếp cận Python rõ ràng là rõ ràng hơn về mặt khái niệm, ngay cả khi nó dài dòng hơn một chút. Bạn lưu trữ trạng thái như bạn làm cho bất cứ điều gì khác. Bạn chỉ cần quấn đầu xung quanh ý tưởng về các đối tượng có thể gọi được. Nhưng bất kể cách tiếp cận nào người ta thích về mặt thẩm mỹ, nó đều thể hiện một sự tôn trọng trong đó Ruby lambdas có cấu trúc mạnh hơn so với Python.


3
Bạn không thể tăng số trong Python, do đó hạn chế không có ý nghĩa. Trong số Python là bất biến. Nếu chúng ta thay đổi nó thành "cộng" thay vào đó, lớp là không cần thiết. Do đó, điều này không chứng minh bất cứ điều gì về sự khác biệt lambda, nhưng sự khác biệt về cách thức hoạt động của các con số. Trừ khi bạn tạo ra một lớp số có thể thay đổi. :)
Lennart Regebro

2
Hạn chế là có để làm rõ hành vi mong muốn. Vấn đề được yêu cầu là: f = foo (10) f (2) >> 12 f (3) >> 15 ... lambda {| i | n + i} đưa ra: f = foo (10) f (2) >> 12 f (3) >> 13 ... Các số cũng không thay đổi trong Ruby - bạn không thể nói 2 + = 1. Và n + = 1 là tốt trong hàm Python thông thường, nhưng không phải là lambda. Vì vậy, vấn đề là "n" là gì, thực tế là nó được tạo ra khi hàm được gọi và lambda được hình thành, rằng bạn có thể thực hiện gán trong lambda (thay vì chỉ biểu thức) và nó có thể giữ giá trị của n qua nhiều cuộc gọi
ký túc xá

Tôi không nghĩ rằng bạn cần phải đi đến độ dài như vậy trong Python. Các chức năng có thể được xác định trong các chức năng khác. def foo(n): def f(i): return n + i return f.
FMc

2
Mặc dù vậy, nó vẫn không giống nhau và ví dụ của bạn tương đương với lambda Python trong bình luận ở trên. Phiên bản Ruby tạo ra lambda giữ trạng thái giữa các cuộc gọi. Ví dụ bạn đã đăng cho phép bạn định cấu hình giá trị bắt đầu cho n, nhưng hàm mà foo trả về sẽ luôn có giá trị bắt đầu đó. Phiên bản Ruby tăng lên. Vì vậy, hãy nói f = foo (10). Phiên bản Python: f (1) => 11, f (1) => 11. Phiên bản Ruby f.call (1) => 11, f.call (1) => 12.
dormsbee

def foo(n): L=[n] def f(i): L[0] += i return L[0] return f. Trong Python3 bạn có thể sử dụng nonlocaltừ khóa.
jfs

3

python đã đặt tên đối số tùy chọn

def func(a, b=2, c=3):
    print a, b, c

>>> func(1)
1 2 3
>>> func(1, c=4)
1 2 4

AFAIK Ruby chỉ có các đối số định vị vì b = 2 trong khai báo hàm là một ảnh hưởng luôn luôn xuất hiện.


3
"Ruby chỉ có các đối số định vị vì b = 2 trong khai báo hàm là một ảnh hưởng luôn luôn nối" có nghĩa là gì?
Horseyguy

3
Bạn không sống trên hành tinh nào, nhưng def my_method(param1, optional = false)hoạt động trong Ruby 1.8.6, 1.8.7 và có lẽ là 1.9!
Robert K

5
Bọ chét độc ác và những người nêu lên nhận xét của anh ta, bạn đã không nhìn vào ví dụ đủ gần. Anh ta có thể bỏ qua btham số trong funccuộc gọi và nó vẫn duy trì mặc định. Đó là, blà đối số thứ hai trong chữ ký, nhưng anh ta có thể bỏ qua nó bằng cách thêm tiền tố vào tham số thứ hai c=. Ruby sử dụng băm để mô phỏng điều này, nhưng nó không hoàn toàn giống nhau.
maček

2

Ruby có tài liệu nhúng:

 =begin

 You could use rdoc to generate man pages from this documentation

 =end

5
Các tài liệu kết thúc như là một phần của các phương thức / lớp bạn đặt chúng vào. Vì vậy, bạn có thể giúp đỡ (lớp) và nó sẽ cho bạn thấy các tài liệu, v.v.
Lennart Regebro


2

Trong Ruby, khi bạn nhập tệp có yêu cầu, 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.

Với Cargo, bạn có thể " yêu cầu các thư viện mà không làm lộn xộn không gian tên của mình ".

# foo-1.0.0.rb
class Foo
  VERSION = "1.0.0"
end

# foo-2.0.0.rb
class Foo
  VERSION = "2.0.0"
end
>> Foo1 = nhập ("foo-1.0.0")
>> Foo2 = nhập ("foo-2.0.0")
>> Foo1 :: PHIÊN BẢN
=> "1.0.0"
>> Foo2 :: PHIÊN BẢN
=> "2.0.0"

Điều này nên được nhận xét, không phải là một câu trả lời mới.
Lennart Regebro
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.