Co takiego ma Ruby, czego nie ma Python i na odwrót?

| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

Istnieje wiele dyskusji na temat Pythona i Rubiego i wszyscy uważam je za całkowicie nieprzydatne, ponieważ wszystkie odwracają się, dlaczego funkcja X jest do bani w języku Y lub twierdzą, że język Y nie ma X, chociaż w rzeczywistości jest Wiem też dokładnie, dlaczego wolę Pythona, ale jest to również subiektywne i nie pomoże nikomu w wyborze, ponieważ mogą nie mieć takich samych gustów w programowaniu jak ja.

Dlatego Ciekawe, aby wymienić różnice, obiektywnie. Więc żadne "lambki Pythona są do bani". Zamiast tego wyjaśnij, co mogą zrobić lambdy Rubiego, a czego nie potrafią Python. Brak subiektywności. Przykładowy kod jest dobry!

Proszę nie mieć kilku różnic w jednej odpowiedzi. I zagłosuj na te, o których wiesz, że są poprawne, a odrzuć te, 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, co Ruby robi z nawiasami i końcami, i że @ w Pythonie nazywa się self.

AKTUALIZACJA: To jest teraz społeczność wiki, więc możemy tutaj dodać duże różnice.

p>

Ruby ma odwołanie do klasy w treści klasy

W Rubim masz odwołanie do klasy (własnej) już w treści klasy. W Pythonie nie masz referencji do klasy, dopóki nie zostanie ukończona budowa klasy.

Przykład:

klasa Kaka umieszcza własny koniec 

w tym przypadku self jest klasą, a ten kod wypisałby „Kaka”. Nie ma możliwości wydrukowania nazwy klasy ani w inny sposób uzyskania dostępu do klasy z treści definicji klasy w Pythonie (poza definicje metod).

Wszystkie klasy są mutowalne w Rubim

Pozwala to na tworzenie rozszerzeń do klas podstawowych. Oto przykład rozszerzenia rails:

 class String def start_with?(other) head = self[0, other.length] head == inny koniec końca 

Python (wyobraź sobie, że nie było "". startz metoda):

def start_with(s, prefiks): return s[:len(prefix)] == prefiks 

Ty może go używać w dowolnej sekwencji (nie tylko w ciągach). Aby go użyć, należy go zaimportować jawnie, np. z jakiegoś_modułu import start_with.

Ruby ma funkcje skryptowe podobne do Perla

Ruby ma pierwszej klasy wyrażenia regularne, zmienne $, pętlę wejściową wiersz po wierszu awk/perl i inne funkcje, które sprawiają, że jest bardziej odpowiedni do pisania małych skryptów powłoki, które usuwają pliki tekstowe lub działają jako kod sklejający 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 wsparcia wbudowanego w język.

Ruby ma bloki

Za pomocą instrukcji „do” możesz utworzyć anonimowa funkcja wiersza w Rubim, która zostanie przekazana jako argument do metody przed do i stamtąd wywoływana. W Pythonie można to zrobić albo przez przekazanie metody, albo przez generatory.

Ruby:

amethod { |tutaj| many=lines+of+code go(tutaj) } 

Python (bloki Ruby odpowiadają różnym konstrukcjom w Pythonie):

z amethod() jako tutaj: # `amethod() to menedżer kontekstu wiele=linii+of+kodu idzie(tutaj) 

Lub

tutaj w amethod() : # `amethod()` to iterowalna funkcja many=lines+of+code (tutaj) 

Lub

funkcja def (tutaj): =lines+of+code go(tutaj) amethod(function) # `funkcja` to wywołanie zwrotne 

Co ciekawe, instrukcja wygody w Ruby do wywołania bloku nazywa się „yield”, co w Pythonie utworzy generator.

Ruby:

def themethod yield 5 end themethod do |foo| puts foo end 

Python:

def themethod(): yield 5 dla foo w themethod(): print foo 

Chociaż zasady są różne, wynik jest uderzająco podobny.

Ruby łatwiej obsługuje programowanie w stylu funkcjonalnym (potokowym)

myList.map(& :description).reject(&:empty?).join(" ") 

Python:

descriptions = (f.description() dla f in mylist) " ".join(filter(len, descriptions)) 

Python ma wbudowane generatory (które są używane jak bloki Rubiego, jak wspomniano powyżej)

Python obsługuje generatory w języku. W Ruby 1.8 możesz użyć modułu generatora, który używa kontynuacji do tworzenia generatora z bloku. Możesz też po prostu użyć bloku/proc/lambda! Ponadto w Ruby 1.9 włókna 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, kiedy importujesz plik z wymagaj, wszystkie rzeczy 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 tworzysz przestrzeń nazw za pomocą modułu, 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 za pomocą z importu modułu *, tym samym zanieczyszczając przestrzeń nazw, jeśli chcesz. Ale możesz również zaimportować tylko wybrane nazwy za pomocą z modułu importuj nazwę, inną lub możesz po prostu zaimportować moduł, a następnie uzyskać dostęp do nazw za pomocą moduł.anazwa. Jeśli chcesz mieć więcej poziomów w swojej przestrzeni nazw, możesz mieć pakiety, które są katalogami z modułami i plikiem __init__.py.

Python ma dokumenty

Docstrings to ciągi, które są dołączone do modułów, funkcji i metod i mogą być przeglądane w czasie wykonywania. Pomaga to w tworzeniu takich rzeczy, jak polecenie pomocy i automatyczna dokumentacja.

def frobnicate(bar): """frobnicate bierze słupek i go frobnicuje >>> bar = Bar( ) >>> bar.is_frobnicated() Fałsz >>>frobnicate(bar) >>> bar.is_frobnicated() Prawda „”” 

Ruby odpowiedniki "s są podobne do javadocs i znajdują się nad metodą, a nie w jej obrębie. Można je pobrać w czasie wykonywania z plików za pomocą metody 1.9" Method#source_location przykładowe użycie

Python ma wielokrotne dziedziczenie

Ruby nie ("celowo" - patrz Witryna Rubiego, zobacz jak to "s zrobione w Ruby). Ponownie wykorzystuje koncepcję modułu jako typ klas abstrakcyjnych.

Python ma wyrażeń list/dict

Python:

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

Ruby:

res = (0..9).map { |x| x * x } 

Python:

>>> (x*x dla x w zakresie(10)) <obiekt generatora <genexpr> pod adresem 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+:

> ;>> {x:str(y*y) dla x,y w {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 ma dekoratory

Rzeczy podobne do dekoratorów można również tworzyć w Ruby, a można również argumentować, że nie są one tak potrzebne jak w Pythonie.

Różnice składni

Ruby wymaga „end” lub „}”, aby zamknąć wszystkie swoje zakresy, podczas gdy Python używa tylko białych znaków. Ostatnio w Rubim próbowano zezwolić tylko na wcięcie białych znaków http://github.com /michaeledgar/bez szwu