Jest wiele dyskusji na temat Pythona kontra Ruby i wszyscy uważam je za całkowicie nieprzydatne, ponieważ wszyscy odwracają się, dlaczego funkcja X jest do kitu w języku Y lub ten język twierdzi, że język Y nie ma X, chociaż w rzeczywistości tak jest. Wiem też dokładnie, dlaczego wolę Python, ale jest to również subiektywne i nie pomogłoby każdemu wybrać, ponieważ mogą nie mieć takich samych upodobań rozwojowych jak ja.
Interesujące byłoby zatem obiektywnie wymienić różnice. Więc nie ma „lambdów Pythona do bani”. Zamiast tego wyjaśnij, co potrafią zrobić jagnięta Ruby, czego nie potrafią Python. Bez podmiotowości. Przykładowy kod jest dobry!
Proszę nie mieć kilku różnic w jednej odpowiedzi. I głosuj w górę na te, o których wiesz, że są poprawne, a na głos, o których wiesz, że są niepoprawne (lub są subiektywne). Również różnice w składni nie są interesujące. Wiemy, że Python robi z wcięciami to, co Ruby robi z nawiasami i końcami, i że @ w Pythonie nazywa się self.
AKTUALIZACJA: To jest teraz wiki społeczności, więc możemy tutaj dodać duże różnice.
Ruby ma odwołanie do klasy w treści klasy
W Ruby masz odniesienie do klasy (ja) już w treści klasy. W Pythonie nie ma odniesienia do klasy, dopóki jej budowa nie zostanie zakończona.
Przykład:
class Kaka
puts self
end
self w tym przypadku jest klasą, a ten kod wypisuje „Kaka”. Nie ma sposobu, aby wydrukować nazwę klasy lub w inny sposób uzyskać dostęp do klasy z treści definicji klasy w Pythonie (poza definicjami metod).
Wszystkie klasy można modyfikować w Ruby
Pozwala to opracowywać rozszerzenia klas podstawowych. Oto przykład rozszerzenia szyny:
class String
def starts_with?(other)
head = self[0, other.length]
head == other
end
end
Python (wyobraź sobie, że nie ma ''.startswithmetody):
def starts_with(s, prefix):
return s[:len(prefix)] == prefix
Możesz użyć go w dowolnej sekwencji (nie tylko w łańcuchach). Aby go użyć, należy go zaimportować jawnie, np from some_module import starts_with.
Ruby ma funkcje skryptowe podobne do Perla
Ruby ma najwyższej klasy wyrażenia regularne, zmienne $, awk / perl wiersz po wierszu i inne funkcje, które sprawiają, że jest bardziej odpowiedni do pisania małych skryptów powłoki, które wyciszają pliki tekstowe lub działają jako kod kleju dla innych programów.
Ruby ma kontynuacje pierwszej klasy
Dzięki instrukcji callcc. W Pythonie możesz tworzyć kontynuacje za pomocą różnych technik, ale nie ma wbudowanej obsługi języka.
Ruby ma bloki
Za pomocą instrukcji „do” możesz utworzyć wieloliniową anonimową funkcję w Ruby, która zostanie przekazana jako argument do metody przed do i wywołana stamtąd. W Pythonie należy to zrobić albo przez przekazanie metody, albo za pomocą generatorów.
Rubin:
amethod { |here|
many=lines+of+code
goes(here)
}
Python (bloki Ruby odpowiadają różnym konstrukcjom w Pythonie):
with amethod() as here: # `amethod() is a context manager
many=lines+of+code
goes(here)
Lub
for here in amethod(): # `amethod()` is an iterable
many=lines+of+code
goes(here)
Lub
def function(here):
many=lines+of+code
goes(here)
amethod(function) # `function` is a callback
Co ciekawe, instrukcja wygody w języku Ruby do wywoływania bloku nazywa się „wydajnością”, która w Pythonie utworzy generator.
Rubin:
def themethod
yield 5
end
themethod do |foo|
puts foo
end
Pyton:
def themethod():
yield 5
for foo in themethod():
print foo
Chociaż zasady są różne, wynik jest uderzająco podobny.
Ruby ułatwia programowanie w stylu funkcjonalnym (przypominającym potok)
myList.map(&:description).reject(&:empty?).join("\n")
Pyton:
descriptions = (f.description() for f in mylist)
"\n".join(filter(len, descriptions))
Python ma wbudowane generatory (które są używane jak bloki Ruby, jak wspomniano powyżej)
Python obsługuje generatory w tym języku. W Ruby 1.8 możesz użyć modułu generatora, który używa kontynuacji do utworzenia generatora z bloku. Lub możesz po prostu użyć bloku / proc / lambda! Co więcej, w Ruby 1.9 Fibres są i mogą być używane jako generatory, a klasa Enumerator jest wbudowanym generatorem 4
docs.python.org ma ten przykład generatora:
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
Porównaj to z powyższymi przykładami bloków.
Python ma elastyczną obsługę przestrzeni nazw
W Ruby, gdy importujesz plik require, wszystkie elementy zdefiniowane w tym pliku znajdą się w twojej globalnej przestrzeni nazw. Powoduje to zanieczyszczenie przestrzeni nazw. Rozwiązaniem tego są moduły Rubys. Ale jeśli utworzysz przestrzeń nazw z modułem, musisz użyć tej przestrzeni nazw, aby uzyskać dostęp do zawartych klas.
W Pythonie plik jest modułem i możesz zaimportować zawarte w nim nazwy from themodule import *, w ten sposób zanieczyszczając przestrzeń nazw, jeśli chcesz. Ale możesz również zaimportować wybrane nazwy za pomocą from themodule import aname, anotherlub możesz po prostu, import themodulea następnie uzyskać dostęp do nazw za pomocą themodule.aname. Jeśli chcesz mieć więcej poziomów w swojej przestrzeni nazw, możesz mieć pakiety, które są katalogami z modułami i __init__.pyplikiem.
Python ma dokumenty
Dokumenty są łańcuchami, które są dołączone do modułów, funkcji i metod i mogą być introspektywne w czasie wykonywania. Pomaga to w tworzeniu takich rzeczy, jak polecenie pomocy i automatyczna dokumentacja.
def frobnicate(bar):
"""frobnicate takes a bar and frobnicates it
>>> bar = Bar()
>>> bar.is_frobnicated()
False
>>> frobnicate(bar)
>>> bar.is_frobnicated()
True
"""
Odpowiedniki Ruby są podobne do javadocs i znajdują się nad metodą zamiast w niej. Można je odzyskać w czasie wykonywania z plików przy użyciu metody 1.9 # przykład użycia source_location
Python ma wiele elementów dziedziczenia
Ruby nie robi tego („celowo” - patrz strona internetowa Ruby, zobacz tutaj, jak to się robi w Ruby ). Ponownie wykorzystuje koncepcję modułu jako rodzaj klas abstrakcyjnych.
Python ma rozumienie list / nagrań
Pyton:
res = [x*x for x in range(1, 10)]
Rubin:
res = (0..9).map { |x| x * x }
Pyton:
>>> (x*x for x in range(10))
<generator object <genexpr> at 0xb7c1ccd4>
>>> list(_)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Rubin:
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'}
Rubin:
>> Hash[{1=>2, 3=>4}.map{|x,y| [x,(y*y).to_s]}]
=> {1=>"4", 3=>"16"}
Python ma dekoratorów
Rzeczy podobne do dekoratorów można również tworzyć w Ruby i można również argumentować, że nie są tak potrzebne jak w Pythonie.
Różnice w składni
Ruby wymaga „end” lub „}”, aby zamknąć wszystkie swoje zakresy, podczas gdy Python używa tylko białych znaków. Ostatnio podjęto w Ruby próby dopuszczenia wcięć tylko w białych znakach http://github.com/michaeledgar/seamless