Wat heeft Ruby dat Python niet heeft, en vice versa?

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

Er zijn veel discussies over Python versus Ruby, en ik vind ze allemaal volkomen nutteloos, omdat ze allemaal omdraaien waarom functie X de taal Y waardeert, of die beweren dat taal Y geen X heeft, hoewel het in feite Ik weet ook precies waarom ik de voorkeur geef aan Python, maar dat is ook subjectief en zou niemand helpen bij het kiezen, omdat ze misschien niet dezelfde smaak in ontwikkeling hebben als ik.

Het zou daarom interessant zijn om de verschillen objectief op te sommen, dus geen "Python's lambda's zuigen". Leg in plaats daarvan uit wat Ruby's lambda's kunnen doen wat Python's niet kunnen. Geen subjectiviteit. Voorbeeldcode is goed!

Heb alsjeblieft niet meerdere verschillen in één antwoord. En stem op degenen waarvan u weet dat ze correct zijn, en omlaag op degenen waarvan u weet dat ze onjuist zijn (of subjectief zijn). Ook zijn verschillen in syntaxis niet interessant. We weten dat Python doet met inspringen wat Ruby doet met haakjes en uiteinden, en dat @ self wordt genoemd in Python.

UPDATE: dit is nu een community-wiki, dus we kunnen de grote verschillen hier toevoegen.

Ruby heeft een class reference in de class body

In Ruby heb je al een reference naar de class (self) in de class body. In Python heb je pas een verwijzing naar de klasse nadat de constructie van de klasse is voltooid.

Een voorbeeld:

class Kaka put self end 

self is in dit geval de klasse, en deze code zou "Kaka" afdrukken. Er is geen manier om de klassenaam af te drukken of op andere manieren toegang te krijgen tot de klasse vanuit de klassedefinitie in Python (buiten methodedefinities).

Alle klassen kunnen worden gewijzigd in Ruby

Hiermee kun je extensies ontwikkelen voor kernklassen. Hier is een voorbeeld van een rails-extensie:

 class String def starts_with?(other) head = self[0, other.length] head == other end end 

Python (stel je voor dat er geen "" was. begintmet methode):

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

U zou het op elke reeks kunnen gebruiken (niet alleen strings). Om het te gebruiken, moet je het expliciet importeren, bijv. from some_module import starts_with.

Ruby heeft Perl-achtige scriptfuncties

Ruby heeft eersteklas regexps, $-variabelen, de awk/perl regel voor regel invoerlus en andere functies die het meer geschikt maken voor het schrijven van kleine shell-scripts die tekstbestanden verminken of fungeren als lijmcode voor andere programma's.

Ruby heeft eersteklas voortzettingen

Dankzij het callcc statement. In Python kun je voortzettingen maken met verschillende technieken, maar er is geen ondersteuning ingebouwd in de taal.

Ruby heeft blokken

Met het "do"-statement kun je een multi- line anonieme functie in Ruby, die als argument wordt doorgegeven aan de methode voor do, en van daaruit wordt aangeroepen. In Python zou je dit in plaats daarvan doen door een methode door te geven of met generatoren.

Ruby:

amethod { |here| many=lines+of+code goes(here) } 

Python (Ruby-blokken komen overeen met verschillende constructies in Python):

met amethod() als hier: # `amethod() is een contextmanager many=lines+of+code goes(her) 

Of

voor hier in amethod() : # `amethod()` is een iterable many=lines+of+code goes(her) 

Or

def function(her): many =lines+of+code goes(her) amethod(function) # `function` is een callback 

Interessant is dat het gemaksstatement in Ruby voor het aanroepen van een blok "yield" wordt genoemd, wat in Python zal een generator maken.

Ruby:

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

Python:

def themethod(): opbrengst 5 voor foo in themethod(): print foo 

Hoewel de principes verschillend zijn, is het resultaat opvallend gelijkaardig.

Ruby ondersteunt gemakkelijker functionele stijl (pipe-achtige) programmering

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

Python:

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

Python heeft ingebouwde generatoren (die worden gebruikt als Ruby-blokken, zoals hierboven vermeld)

Python heeft ondersteuning voor generatoren in de taal. In Ruby 1.8 kun je de generatormodule gebruiken die voortzettingen gebruikt om een generator van een blok te maken. Of je kunt gewoon een block/proc/lambda gebruiken! Bovendien zijn in Ruby 1.9 Fibers, en kunnen ze worden gebruikt als, generatoren, en is de Enumerator-klasse een ingebouwde generator 4

docs.python. org heeft dit generatorvoorbeeld:

def reverse(data): for index in range(len(data)-1, -1, -1): opbrengstgegevens[index] 

Vergelijk dit met de bovenstaande blokvoorbeelden.

Python heeft flexibele verwerking van naamruimte

In Ruby, wanneer u een bestand importeert met vereist, alle dingen die in dat bestand zijn gedefinieerd, komen in uw algemene naamruimte terecht. Dit veroorzaakt vervuiling van de naamruimte. De oplossing daarvoor zijn Rubys-modules. Maar als je een naamruimte maakt met een module, dan moet je die naamruimte gebruiken om toegang te krijgen tot de ingesloten klassen.

In Python is het bestand een module en je kunt de ingesloten namen importeren met uit de module import *, waardoor de naamruimte wordt vervuild als je wilt. Maar u kunt ook alleen geselecteerde namen importeren met uit de module importeer een naam, een andere of u kunt eenvoudig demodule importeren en vervolgens toegang krijgen tot de namen met demodule.anaam. Als u meer niveaus in uw naamruimte wilt, kunt u pakketten hebben, dit zijn mappen met modules en een __init__.py-bestand.

Python heeft docstrings

Docstrings zijn strings die zijn gekoppeld aan modules, functies en methoden en die tijdens runtime kunnen worden bekeken. Dit helpt bij het maken van zaken als het help-commando en automatische documentatie.

def frobnicate(bar): """frobnicate neemt een bar en frobniceert deze >>> bar = Bar( ) >>> bar.is_frobnicated() False >>> frobnicate(bar) >>> bar.is_frobnicated() True """ 

Ruby "s-equivalenten zijn vergelijkbaar met javadocs en bevinden zich boven de methode in plaats van erin. Ze kunnen tijdens runtime worden opgehaald uit de bestanden met behulp van 1.9"s Method#source_location example use

Python heeft meervoudige overerving

Ruby doet dat niet ("met opzet" -- zie Ruby's website, zie hier hoe het "is gedaan in Ruby). Het hergebruikt het moduleconcept als een soort abstracte klassen.

Python heeft lijst-/dictaatbegrippen

Python:

res = [x* x voor x binnen bereik(1, 10)] 

Ruby:

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

Python:

>>> (x*x voor x in bereik(10)) <generator object <genexpr> op 0xb7c1ccd4> >>> list(_) [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 

Ruby:

p = proces { |x| x * x } (0..9).map(&p) 

Python 2.7+:

> ;>> {x:str(y*y) voor 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 heeft decorateurs

Dingen die vergelijkbaar zijn met decorateurs kunnen ook worden gemaakt in Ruby, en er kan ook worden beweerd dat ze niet zo noodzakelijk zijn als in Python.

Syntaxisverschillen

Ruby vereist "end" of "}" om alle scopes te sluiten, terwijl Python gebruikt alleen witruimte. Er zijn recente pogingen geweest in Ruby om alleen witruimte inspringen toe te staan http://github.com /michaeledgar/naadloos