2010-09-25 12 views
20

Ho cercato le somiglianze/differenze tra i generatori Ruby e Python (noto come Enumerators in Ruby), e per quanto posso dire che sono praticamente equivalenti.Generatori di Ruby vs generatori Python

Tuttavia, una differenza che ho notato è che i Generatori Python supportano un metodo close() mentre Ruby Generator no. Dalla documentazione Python metodo close() è detto di effettuare le seguenti operazioni:

solleva un GeneratorExit nel punto in cui è stato sospeso il funzionamento del generatore. Se la funzione di generatore poi solleva StopIteration (uscendo normalmente, oppure a causa di già essere chiuso) o GeneratorExit (da non cattura l'eccezione), torna vicino al chiamante ".

C'è una buona ragione per la quale Rubino Enumerators non supportano il metodo close()? O è un accidentale omissione?

ho anche scoperto che Ruby Enumerators supporto di un metodo rewind() ancora generatori Python non lo fanno ... c'è un motivo anche per questo?

Grazie

+0

Curioso, ma non capisco come lo useresti: puoi fare un esempio? –

+5

@Andrew Vit: questo può essere usato per causare risorse - connessioni database, file, ecc. - detenute dal generatore da ripulire.Impedirà inoltre ulteriori chiamate ai suoi metodi 'next' o' send' da altre parti del codice. Ad esempio, è possibile chiamare "chiudi" per indicare da uno dei numerosi consumatori di indicare agli altri che è stato trovato il valore desiderato. – intuited

+0

@intuited, è il 'close()' di Python effettivamente usato anche se? Penso di aver letto da qualche parte che è considerato "arcano" dalla comunità di Python e non realmente utilizzato. – horseyguy

risposta

2

I generatori sono basati sullo stack, gli enumeratori di Ruby sono spesso specializzati (a livello di interprete) e non basati sullo stack.

1

classe di uso del StopIteration di Ruby Enumeratore internamente, vedere How do Enumerators work in Ruby 1.9.1?

(è appena concluso se lo si utilizza in una per ogni chiamata). Quindi direi che sono piuttosto vicini. Detto questo, non sono sicuro di quale metodo vicino su un enumeratore dovrebbe fare, esattamente ... pulizia, forse? (Probabilmente i generatori di Python trarrebbero beneficio da un riavvolgimento - si noti bene che in Ruby alcuni enumeratori non rispondono al riavvolgimento, quindi sollevano un'eccezione quando si chiama quel metodo).

+2

grazie per la tua risposta. Ma 'StopIteration' è ciò che usa anche Python - in effetti Ruby ha preso questa idea da Python hehe. Per quanto riguarda ciò che potrebbe fare un 'close()', guarda il commento di intuited alla mia domanda (sopra). – horseyguy

+0

yeah l'enumeratore di Ruby 1.9.x fondamentalmente lo ha messo in linea con Python's Generator (anche se puoi anche solo usare un blocco in Ruby per simulare un generatore, davvero). – rogerdpack

6

Questo documentation for the rewind method è un po 'scarso sui dettagli. Ma al fine di "ricominciare da capo", il generatore avrebbe dovuto fare una delle due cose:

  • ricordare la sua uscita completa, ripetere che la produzione una volta riavvolto, per poi riprendere quello che stava facendo prima
  • ripristinare il suo stato interno in un modo che fa ripetere lo stesso output senza altri effetti collaterali indesiderati

Il secondo di questi non è sempre possibile; ad esempio, se il generatore emette buffer di byte dalla rete, l'output non è interamente una funzione dello stato interno. Ma qualsiasi generatore che usi la prima tecnica deve necessariamente costruire un buffer più grande e più grande in memoria come viene utilizzato. Tali generatori offrono scarso beneficio sulle liste.

Pertanto, concludo che il metodo Ruby rewind deve essere facoltativo e non sempre supportato da una classe di enumeratore concreta. Quindi, se i designer Python danno valore allo Liskov substitution principle, ciò li indurrebbe a non richiedere un tale metodo in tutti i generatori.