it-swarm.it

Scopo del "ritorno di sé" da un metodo di classe?

Mi sono imbattuto in qualcosa di simile in un progetto open source. I metodi che modificano gli attributi dell'istanza restituiscono un riferimento all'istanza. Qual è lo scopo di questo costrutto?

class Foo(object):

  def __init__(self):
    self.myattr = 0

  def bar(self):
    self.myattr += 1
    return self
46
nate c

È per consentire il concatenamento.

Per esempio:

var Car = function () {
    return {
        gas : 0,
        miles : 0,
        drive : function (d) {
            this.miles += d;
            this.gas -= d;
            return this;
        },
        fill : function (g) {
            this.gas += g;
            return this;
        },
    };
}

Ora puoi dire:

var c = Car();
c.fill(100).drive(50);
c.miles => 50;
c.gas => 50;
66
Josh K

Come menzionano @Lie Ryan e @Frank Shearar, questa si chiama "interfaccia fluente" ma quel modello esiste da molto tempo.

La parte controversa di quel modello è che in OO hai uno stato mutabile, quindi un metodo void ha una sorta di valore di ritorno implicito di this - cioè, l'oggetto con stato aggiornato è tipo del valore di ritorno .

Quindi in un linguaggio OO con stato mutabile, questi due sono più o meno equivalenti:

a.doA()
a.doB()
a.doC()

... al contrario di

a.doA().doB().doC()

Quindi ho sentito persone in passato resistere alle interfacce fluide perché a loro piace la prima forma. Un altro nome che ho sentito per "interfaccia fluente" è "disastro ferroviario";)

Dico "più o meno equivalenti", tuttavia, perché le interfacce fluide aggiungono una ruga. Non devono "restituire questo". Possono "tornare nuovi". Questo è un modo per raggiungere oggetti immutabili in OO.

Quindi potresti avere una classe A che lo fa (pseudocodice)

function doA():
    return new A(value + 1)

function doB():
    return new A(value * 2)

function doC():
    return new A(sqrt(value))

Ora, ogni metodo restituisce un oggetto nuovo di zecca, lasciando invariato l'oggetto iniziale. E questo è un modo per entrare in oggetti immutabili senza cambiare molto nel tuo codice.

10
Rob

La maggior parte delle lingue è a conoscenza del linguaggio del "sé di ritorno" e lo ignora se non viene utilizzato in una riga. Tuttavia è da notare che in Python, le funzioni restituiscono None per impostazione predefinita.

Quando ero a scuola CS il mio istruttore ha fatto un affare enorme sulla differenza tra funzioni, procedure, routine e metodi; molte domande sul tema dei crampi alle mani sono state risolte con matite meccaniche che mi si scaldavano nelle mani.

Basti dire che il ritorno di sé è il modo definitivo OO per creare metodi di classe, ma Python consente più valori di ritorno, tuple, liste, oggetti, primitive o nessuno.

Il concatenamento, come dicono, sta semplicemente mettendo la risposta all'ultima operazione nella successiva, e il tempo di esecuzione di Python può ottimizzare quel tipo di cose. Le comprensioni dell'elenco sono una forma incorporata di questo. (Molto potente!)

Quindi in Python non è così importante che ogni metodo o funzione restituisca cose, motivo per cui il valore predefinito è None.

Esiste una scuola di pensiero secondo cui ogni azione in un programma dovrebbe riportare il suo successo, fallimento o ricondurre al suo contesto o oggetto invocante, ma non parlava qui dei requisiti ADA di DOD. Se hai bisogno di ricevere feedback da un metodo, vai avanti o no, ma cerca di essere coerente al riguardo.

Se un metodo può fallire, dovrebbe restituire successo o fallimento o sollevare un'eccezione da gestire.

Un avvertimento è che se usi il ritorno del linguaggio personale, Python ti consentirà di assegnare tutti i tuoi metodi alle variabili e potresti pensare che stai ottenendo un risultato di dati o un elenco quando stai effettivamente ottenendo l'oggetto.

I linguaggi restrittivi dei tipi gridano, gridano e si rompono quando provi a farlo, ma quelli interpretati (Python, Lua, LISP) sono molto più dinamici.

8
Chris Reid

In Smalltalk, ogni metodo che non restituisce esplicitamente qualcosa, ha un implicito "ritorno di sé".

Questo perché (a) avere ogni metodo restituisce qualcosa rende il modello di calcolo più uniforme e (b) è molto utile avere i metodi restituiscono se stessi. Josh K fa un bell'esempio.

4
Frank Shearar

Pro di restituzione di un oggetto (return self)

  • Esempio:

    print(foo.modify1().modify2())
    
    # instaed of
    foo.modify1()
    foo.modify2()
    print(foo)
    
  • Stile più popolare nella comunità di programmazione (penso).

Pro di mutazione di un oggetto (no return self)

  • Possibilità di usare return per altri scopi.
  • Guido van Rossum approva questo stile (Non sono d'accordo con il suo argomento).
  • Stile più popolare in Python community (credo).
  • Predefinito (meno codice sorgente).
2
xged